diff options
280 files changed, 10940 insertions, 6951 deletions
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index debf6813934a..866b76139420 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt | |||
| @@ -253,7 +253,7 @@ Here are the routines, one by one: | |||
| 253 | 253 | ||
| 254 | The first of these two routines is invoked after map_vm_area() | 254 | The first of these two routines is invoked after map_vm_area() |
| 255 | has installed the page table entries. The second is invoked | 255 | has installed the page table entries. The second is invoked |
| 256 | before unmap_vm_area() deletes the page table entries. | 256 | before unmap_kernel_range() deletes the page table entries. |
| 257 | 257 | ||
| 258 | There exists another whole class of cpu cache issues which currently | 258 | There exists another whole class of cpu cache issues which currently |
| 259 | require a whole different set of interfaces to handle properly. | 259 | require a whole different set of interfaces to handle properly. |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3a159dac04f5..55b5d6a210d8 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -330,3 +330,15 @@ Who: Tejun Heo <htejun@gmail.com> | |||
| 330 | 330 | ||
| 331 | --------------------------- | 331 | --------------------------- |
| 332 | 332 | ||
| 333 | What: The arch/ppc and include/asm-ppc directories | ||
| 334 | When: Jun 2008 | ||
| 335 | Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64 | ||
| 336 | platforms. Currently there are efforts underway to port the remaining | ||
| 337 | arch/ppc platforms to the merged tree. New submissions to the arch/ppc | ||
| 338 | tree have been frozen with the 2.6.22 kernel release and that tree will | ||
| 339 | remain in bug-fix only mode until its scheduled removal. Platforms | ||
| 340 | that are not ported by June 2008 will be removed due to the lack of an | ||
| 341 | interested maintainer. | ||
| 342 | Who: linuxppc-dev@ozlabs.org | ||
| 343 | |||
| 344 | --------------------------- | ||
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index d42d98107d49..0c2434822094 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
| @@ -42,15 +42,16 @@ Table of Contents | |||
| 42 | 1) Defining child nodes of an SOC | 42 | 1) Defining child nodes of an SOC |
| 43 | 2) Representing devices without a current OF specification | 43 | 2) Representing devices without a current OF specification |
| 44 | a) MDIO IO device | 44 | a) MDIO IO device |
| 45 | c) PHY nodes | ||
| 46 | b) Gianfar-compatible ethernet nodes | 45 | b) Gianfar-compatible ethernet nodes |
| 46 | c) PHY nodes | ||
| 47 | d) Interrupt controllers | 47 | d) Interrupt controllers |
| 48 | e) I2C | 48 | e) I2C |
| 49 | f) Freescale SOC USB controllers | 49 | f) Freescale SOC USB controllers |
| 50 | g) Freescale SOC SEC Security Engines | 50 | g) Freescale SOC SEC Security Engines |
| 51 | h) Board Control and Status (BCSR) | 51 | h) Board Control and Status (BCSR) |
| 52 | i) Freescale QUICC Engine module (QE) | 52 | i) Freescale QUICC Engine module (QE) |
| 53 | g) Flash chip nodes | 53 | j) Flash chip nodes |
| 54 | k) Global Utilities Block | ||
| 54 | 55 | ||
| 55 | VII - Specifying interrupt information for devices | 56 | VII - Specifying interrupt information for devices |
| 56 | 1) interrupts property | 57 | 1) interrupts property |
| @@ -626,6 +627,14 @@ So the node content can be summarized as a start token, a full path, | |||
| 626 | a list of properties, a list of child nodes, and an end token. Every | 627 | a list of properties, a list of child nodes, and an end token. Every |
| 627 | child node is a full node structure itself as defined above. | 628 | child node is a full node structure itself as defined above. |
| 628 | 629 | ||
| 630 | NOTE: The above definition requires that all property definitions for | ||
| 631 | a particular node MUST precede any subnode definitions for that node. | ||
| 632 | Although the structure would not be ambiguous if properties and | ||
| 633 | subnodes were intermingled, the kernel parser requires that the | ||
| 634 | properties come first (up until at least 2.6.22). Any tools | ||
| 635 | manipulating a flattened tree must take care to preserve this | ||
| 636 | constraint. | ||
| 637 | |||
| 629 | 4) Device tree "strings" block | 638 | 4) Device tree "strings" block |
| 630 | 639 | ||
| 631 | In order to save space, property names, which are generally redundant, | 640 | In order to save space, property names, which are generally redundant, |
| @@ -1782,6 +1791,33 @@ platforms are moved over to use the flattened-device-tree model. | |||
| 1782 | partition-names = "fs\0firmware"; | 1791 | partition-names = "fs\0firmware"; |
| 1783 | }; | 1792 | }; |
| 1784 | 1793 | ||
| 1794 | k) Global Utilities Block | ||
| 1795 | |||
| 1796 | The global utilities block controls power management, I/O device | ||
| 1797 | enabling, power-on-reset configuration monitoring, general-purpose | ||
| 1798 | I/O signal configuration, alternate function selection for multiplexed | ||
| 1799 | signals, and clock control. | ||
| 1800 | |||
| 1801 | Required properties: | ||
| 1802 | |||
| 1803 | - compatible : Should define the compatible device type for | ||
| 1804 | global-utilities. | ||
| 1805 | - reg : Offset and length of the register set for the device. | ||
| 1806 | |||
| 1807 | Recommended properties: | ||
| 1808 | |||
| 1809 | - fsl,has-rstcr : Indicates that the global utilities register set | ||
| 1810 | contains a functioning "reset control register" (i.e. the board | ||
| 1811 | is wired to reset upon setting the HRESET_REQ bit in this register). | ||
| 1812 | |||
| 1813 | Example: | ||
| 1814 | |||
| 1815 | global-utilities@e0000 { /* global utilities block */ | ||
| 1816 | compatible = "fsl,mpc8548-guts"; | ||
| 1817 | reg = <e0000 1000>; | ||
| 1818 | fsl,has-rstcr; | ||
| 1819 | }; | ||
| 1820 | |||
| 1785 | More devices will be defined as this spec matures. | 1821 | More devices will be defined as this spec matures. |
| 1786 | 1822 | ||
| 1787 | VII - Specifying interrupt information for devices | 1823 | VII - Specifying interrupt information for devices |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5eaeafd30bdf..cbfbd981cdcd 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -4,17 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | mainmenu "Linux/PowerPC Kernel Configuration" | 5 | mainmenu "Linux/PowerPC Kernel Configuration" |
| 6 | 6 | ||
| 7 | config PPC64 | 7 | source "arch/powerpc/platforms/Kconfig.cputype" |
| 8 | bool "64-bit kernel" | ||
| 9 | default n | ||
| 10 | help | ||
| 11 | This option selects whether a 32-bit or a 64-bit kernel | ||
| 12 | will be built. | ||
| 13 | |||
| 14 | config PPC_PM_NEEDS_RTC_LIB | ||
| 15 | bool | ||
| 16 | select RTC_LIB | ||
| 17 | default y if PM | ||
| 18 | 8 | ||
| 19 | config PPC32 | 9 | config PPC32 |
| 20 | bool | 10 | bool |
| @@ -132,123 +122,6 @@ config PPC64_SWSUSP | |||
| 132 | depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) | 122 | depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) |
| 133 | default y | 123 | default y |
| 134 | 124 | ||
| 135 | menu "Processor support" | ||
| 136 | choice | ||
| 137 | prompt "Processor Type" | ||
| 138 | depends on PPC32 | ||
| 139 | default 6xx | ||
| 140 | |||
| 141 | config CLASSIC32 | ||
| 142 | bool "52xx/6xx/7xx/74xx" | ||
| 143 | select PPC_FPU | ||
| 144 | select 6xx | ||
| 145 | help | ||
| 146 | There are four families of PowerPC chips supported. The more common | ||
| 147 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded | ||
| 148 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC | ||
| 149 | embedded versions (403 and 405) and the high end 64 bit Power | ||
| 150 | processors (POWER 3, POWER4, and IBM PPC970 also known as G5). | ||
| 151 | |||
| 152 | This option is the catch-all for 6xx types, including some of the | ||
| 153 | embedded versions. Unless there is see an option for the specific | ||
| 154 | chip family you are using, you want this option. | ||
| 155 | |||
| 156 | You do not want this if you are building a kernel for a 64 bit | ||
| 157 | IBM RS/6000 or an Apple G5, choose 6xx. | ||
| 158 | |||
| 159 | If unsure, select this option | ||
| 160 | |||
| 161 | Note that the kernel runs in 32-bit mode even on 64-bit chips. | ||
| 162 | |||
| 163 | config PPC_82xx | ||
| 164 | bool "Freescale 82xx" | ||
| 165 | select 6xx | ||
| 166 | select PPC_FPU | ||
| 167 | |||
| 168 | config PPC_83xx | ||
| 169 | bool "Freescale 83xx" | ||
| 170 | select 6xx | ||
| 171 | select FSL_SOC | ||
| 172 | select 83xx | ||
| 173 | select PPC_FPU | ||
| 174 | select WANT_DEVICE_TREE | ||
| 175 | |||
| 176 | config PPC_85xx | ||
| 177 | bool "Freescale 85xx" | ||
| 178 | select E500 | ||
| 179 | select FSL_SOC | ||
| 180 | select 85xx | ||
| 181 | select WANT_DEVICE_TREE | ||
| 182 | |||
| 183 | config PPC_86xx | ||
| 184 | bool "Freescale 86xx" | ||
| 185 | select 6xx | ||
| 186 | select FSL_SOC | ||
| 187 | select FSL_PCIE | ||
| 188 | select PPC_FPU | ||
| 189 | select ALTIVEC | ||
| 190 | help | ||
| 191 | The Freescale E600 SoCs have 74xx cores. | ||
| 192 | |||
| 193 | config PPC_8xx | ||
| 194 | bool "Freescale 8xx" | ||
| 195 | select FSL_SOC | ||
| 196 | select 8xx | ||
| 197 | |||
| 198 | config 40x | ||
| 199 | bool "AMCC 40x" | ||
| 200 | select PPC_DCR_NATIVE | ||
| 201 | |||
| 202 | config 44x | ||
| 203 | bool "AMCC 44x" | ||
| 204 | select PPC_DCR_NATIVE | ||
| 205 | select WANT_DEVICE_TREE | ||
| 206 | |||
| 207 | config E200 | ||
| 208 | bool "Freescale e200" | ||
| 209 | |||
| 210 | endchoice | ||
| 211 | |||
| 212 | config POWER4_ONLY | ||
| 213 | bool "Optimize for POWER4" | ||
| 214 | depends on PPC64 | ||
| 215 | default n | ||
| 216 | ---help--- | ||
| 217 | Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. | ||
| 218 | The resulting binary will not work on POWER3 or RS64 processors | ||
| 219 | when compiled with binutils 2.15 or later. | ||
| 220 | |||
| 221 | config POWER3 | ||
| 222 | bool | ||
| 223 | depends on PPC64 | ||
| 224 | default y if !POWER4_ONLY | ||
| 225 | |||
| 226 | config POWER4 | ||
| 227 | depends on PPC64 | ||
| 228 | def_bool y | ||
| 229 | |||
| 230 | config 6xx | ||
| 231 | bool | ||
| 232 | |||
| 233 | # this is temp to handle compat with arch=ppc | ||
| 234 | config 8xx | ||
| 235 | bool | ||
| 236 | |||
| 237 | # this is temp to handle compat with arch=ppc | ||
| 238 | config 83xx | ||
| 239 | bool | ||
| 240 | |||
| 241 | # this is temp to handle compat with arch=ppc | ||
| 242 | config 85xx | ||
| 243 | bool | ||
| 244 | |||
| 245 | config E500 | ||
| 246 | bool | ||
| 247 | |||
| 248 | config PPC_FPU | ||
| 249 | bool | ||
| 250 | default y if PPC64 | ||
| 251 | |||
| 252 | config PPC_DCR_NATIVE | 125 | config PPC_DCR_NATIVE |
| 253 | bool | 126 | bool |
| 254 | default n | 127 | default n |
| @@ -267,134 +140,6 @@ config PPC_OF_PLATFORM_PCI | |||
| 267 | depends on PPC64 # not supported on 32 bits yet | 140 | depends on PPC64 # not supported on 32 bits yet |
| 268 | default n | 141 | default n |
| 269 | 142 | ||
| 270 | config 4xx | ||
| 271 | bool | ||
| 272 | depends on 40x || 44x | ||
| 273 | default y | ||
| 274 | |||
| 275 | config BOOKE | ||
| 276 | bool | ||
| 277 | depends on E200 || E500 || 44x | ||
| 278 | default y | ||
| 279 | |||
| 280 | config FSL_BOOKE | ||
| 281 | bool | ||
| 282 | depends on E200 || E500 | ||
| 283 | default y | ||
| 284 | |||
| 285 | config PTE_64BIT | ||
| 286 | bool | ||
| 287 | depends on 44x || E500 | ||
| 288 | default y if 44x | ||
| 289 | default y if E500 && PHYS_64BIT | ||
| 290 | |||
| 291 | config PHYS_64BIT | ||
| 292 | bool 'Large physical address support' if E500 | ||
| 293 | depends on 44x || E500 | ||
| 294 | select RESOURCES_64BIT | ||
| 295 | default y if 44x | ||
| 296 | ---help--- | ||
| 297 | This option enables kernel support for larger than 32-bit physical | ||
| 298 | addresses. This features is not be available on all e500 cores. | ||
| 299 | |||
| 300 | If in doubt, say N here. | ||
| 301 | |||
| 302 | config ALTIVEC | ||
| 303 | bool "AltiVec Support" | ||
| 304 | depends on CLASSIC32 || POWER4 | ||
| 305 | ---help--- | ||
| 306 | This option enables kernel support for the Altivec extensions to the | ||
| 307 | PowerPC processor. The kernel currently supports saving and restoring | ||
| 308 | altivec registers, and turning on the 'altivec enable' bit so user | ||
| 309 | processes can execute altivec instructions. | ||
| 310 | |||
| 311 | This option is only usefully if you have a processor that supports | ||
| 312 | altivec (G4, otherwise known as 74xx series), but does not have | ||
| 313 | any affect on a non-altivec cpu (it does, however add code to the | ||
| 314 | kernel). | ||
| 315 | |||
| 316 | If in doubt, say Y here. | ||
| 317 | |||
| 318 | config SPE | ||
| 319 | bool "SPE Support" | ||
| 320 | depends on E200 || E500 | ||
| 321 | default y | ||
| 322 | ---help--- | ||
| 323 | This option enables kernel support for the Signal Processing | ||
| 324 | Extensions (SPE) to the PowerPC processor. The kernel currently | ||
| 325 | supports saving and restoring SPE registers, and turning on the | ||
| 326 | 'spe enable' bit so user processes can execute SPE instructions. | ||
| 327 | |||
| 328 | This option is only useful if you have a processor that supports | ||
| 329 | SPE (e500, otherwise known as 85xx series), but does not have any | ||
| 330 | effect on a non-spe cpu (it does, however add code to the kernel). | ||
| 331 | |||
| 332 | If in doubt, say Y here. | ||
| 333 | |||
| 334 | config PPC_STD_MMU | ||
| 335 | bool | ||
| 336 | depends on 6xx || POWER3 || POWER4 || PPC64 | ||
| 337 | default y | ||
| 338 | |||
| 339 | config PPC_STD_MMU_32 | ||
| 340 | def_bool y | ||
| 341 | depends on PPC_STD_MMU && PPC32 | ||
| 342 | |||
| 343 | config PPC_MM_SLICES | ||
| 344 | bool | ||
| 345 | default y if HUGETLB_PAGE | ||
| 346 | default n | ||
| 347 | |||
| 348 | config VIRT_CPU_ACCOUNTING | ||
| 349 | bool "Deterministic task and CPU time accounting" | ||
| 350 | depends on PPC64 | ||
| 351 | default y | ||
| 352 | help | ||
| 353 | Select this option to enable more accurate task and CPU time | ||
| 354 | accounting. This is done by reading a CPU counter on each | ||
| 355 | kernel entry and exit and on transitions within the kernel | ||
| 356 | between system, softirq and hardirq state, so there is a | ||
| 357 | small performance impact. This also enables accounting of | ||
| 358 | stolen time on logically-partitioned systems running on | ||
| 359 | IBM POWER5-based machines. | ||
| 360 | |||
| 361 | If in doubt, say Y here. | ||
| 362 | |||
| 363 | config SMP | ||
| 364 | depends on PPC_STD_MMU | ||
| 365 | bool "Symmetric multi-processing support" | ||
| 366 | ---help--- | ||
| 367 | This enables support for systems with more than one CPU. If you have | ||
| 368 | a system with only one CPU, say N. If you have a system with more | ||
| 369 | than one CPU, say Y. Note that the kernel does not currently | ||
| 370 | support SMP machines with 603/603e/603ev or PPC750 ("G3") processors | ||
| 371 | since they have inadequate hardware support for multiprocessor | ||
| 372 | operation. | ||
| 373 | |||
| 374 | If you say N here, the kernel will run on single and multiprocessor | ||
| 375 | machines, but will use only one CPU of a multiprocessor machine. If | ||
| 376 | you say Y here, the kernel will run on single-processor machines. | ||
| 377 | On a single-processor machine, the kernel will run faster if you say | ||
| 378 | N here. | ||
| 379 | |||
| 380 | If you don't know what to do here, say N. | ||
| 381 | |||
| 382 | config NR_CPUS | ||
| 383 | int "Maximum number of CPUs (2-128)" | ||
| 384 | range 2 128 | ||
| 385 | depends on SMP | ||
| 386 | default "32" if PPC64 | ||
| 387 | default "4" | ||
| 388 | |||
| 389 | config NOT_COHERENT_CACHE | ||
| 390 | bool | ||
| 391 | depends on 4xx || 8xx || E200 | ||
| 392 | default y | ||
| 393 | |||
| 394 | config CONFIG_CHECK_CACHE_COHERENCY | ||
| 395 | bool | ||
| 396 | endmenu | ||
| 397 | |||
| 398 | source "init/Kconfig" | 143 | source "init/Kconfig" |
| 399 | 144 | ||
| 400 | source "arch/powerpc/platforms/Kconfig" | 145 | source "arch/powerpc/platforms/Kconfig" |
| @@ -674,10 +419,6 @@ config SBUS | |||
| 674 | config FSL_SOC | 419 | config FSL_SOC |
| 675 | bool | 420 | bool |
| 676 | 421 | ||
| 677 | config FSL_PCIE | ||
| 678 | bool | ||
| 679 | depends on PPC_86xx | ||
| 680 | |||
| 681 | # Yes MCA RS/6000s exist but Linux-PPC does not currently support any | 422 | # Yes MCA RS/6000s exist but Linux-PPC does not currently support any |
| 682 | config MCA | 423 | config MCA |
| 683 | bool | 424 | bool |
| @@ -685,10 +426,10 @@ config MCA | |||
| 685 | config PCI | 426 | config PCI |
| 686 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | 427 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ |
| 687 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ | 428 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ |
| 688 | || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY | 429 | || PPC_PS3 |
| 689 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ | 430 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ |
| 690 | && !PPC_85xx && !PPC_86xx | 431 | && !PPC_85xx && !PPC_86xx |
| 691 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS | 432 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx |
| 692 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 433 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
| 693 | select ARCH_SUPPORTS_MSI | 434 | select ARCH_SUPPORTS_MSI |
| 694 | help | 435 | help |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index fbafd965dcd2..187a39af3e1c 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
| @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) | |||
| 148 | 148 | ||
| 149 | CPPFLAGS_vmlinux.lds := -Upowerpc | 149 | CPPFLAGS_vmlinux.lds := -Upowerpc |
| 150 | 150 | ||
| 151 | BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage | 151 | BOOT_TARGETS = zImage zImage.initrd uImage |
| 152 | 152 | ||
| 153 | PHONY += $(BOOT_TARGETS) | 153 | PHONY += $(BOOT_TARGETS) |
| 154 | 154 | ||
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c index d51377d9024f..9f64e840bef6 100644 --- a/arch/powerpc/boot/44x.c +++ b/arch/powerpc/boot/44x.c | |||
| @@ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void) | |||
| 38 | 38 | ||
| 39 | dt_fixup_memory(0, memsize); | 39 | dt_fixup_memory(0, memsize); |
| 40 | } | 40 | } |
| 41 | |||
| 42 | #define SPRN_DBCR0 0x134 | ||
| 43 | #define DBCR0_RST_SYSTEM 0x30000000 | ||
| 44 | |||
| 45 | void ibm44x_dbcr_reset(void) | ||
| 46 | { | ||
| 47 | unsigned long tmp; | ||
| 48 | |||
| 49 | asm volatile ( | ||
| 50 | "mfspr %0,%1\n" | ||
| 51 | "oris %0,%0,%2@h\n" | ||
| 52 | "mtspr %1,%0" | ||
| 53 | : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||
| 54 | ); | ||
| 55 | |||
| 56 | } | ||
| 57 | |||
| 58 | /* Read 4xx EBC bus bridge registers to get mappings of the peripheral | ||
| 59 | * banks into the OPB address space */ | ||
| 60 | void ibm4xx_fixup_ebc_ranges(const char *ebc) | ||
| 61 | { | ||
| 62 | void *devp; | ||
| 63 | u32 bxcr; | ||
| 64 | u32 ranges[EBC_NUM_BANKS*4]; | ||
| 65 | u32 *p = ranges; | ||
| 66 | int i; | ||
| 67 | |||
| 68 | for (i = 0; i < EBC_NUM_BANKS; i++) { | ||
| 69 | mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i)); | ||
| 70 | bxcr = mfdcr(DCRN_EBC0_CFGDATA); | ||
| 71 | |||
| 72 | if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) { | ||
| 73 | *p++ = i; | ||
| 74 | *p++ = 0; | ||
| 75 | *p++ = bxcr & EBC_BXCR_BAS; | ||
| 76 | *p++ = EBC_BXCR_BANK_SIZE(bxcr); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | devp = finddevice(ebc); | ||
| 81 | if (! devp) | ||
| 82 | fatal("Couldn't locate EBC node %s\n\r", ebc); | ||
| 83 | |||
| 84 | setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32)); | ||
| 85 | } | ||
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h index 7b129ad043e1..577982c9a3cd 100644 --- a/arch/powerpc/boot/44x.h +++ b/arch/powerpc/boot/44x.h | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | #define _PPC_BOOT_44X_H_ | 11 | #define _PPC_BOOT_44X_H_ |
| 12 | 12 | ||
| 13 | void ibm44x_fixup_memsize(void); | 13 | void ibm44x_fixup_memsize(void); |
| 14 | void ibm4xx_fixup_ebc_ranges(const char *ebc); | ||
| 15 | |||
| 16 | void ibm44x_dbcr_reset(void); | ||
| 14 | void ebony_init(void *mac0, void *mac1); | 17 | void ebony_init(void *mac0, void *mac1); |
| 15 | 18 | ||
| 16 | #endif /* _PPC_BOOT_44X_H_ */ | 19 | #endif /* _PPC_BOOT_44X_H_ */ |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index ff2701949ee1..61a6f34ca5ed 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
| @@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ | |||
| 43 | 43 | ||
| 44 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ | 44 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ |
| 45 | ns16550.c serial.c simple_alloc.c div64.S util.S \ | 45 | ns16550.c serial.c simple_alloc.c div64.S util.S \ |
| 46 | gunzip_util.c elf_util.c $(zlib) devtree.c \ | 46 | gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ |
| 47 | 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c | 47 | 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c |
| 48 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ | 48 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ |
| 49 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c | 49 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ |
| 50 | ps3-head.S ps3-hvcall.S ps3.c | ||
| 50 | src-boot := $(src-wlib) $(src-plat) empty.c | 51 | src-boot := $(src-wlib) $(src-plat) empty.c |
| 51 | 52 | ||
| 52 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 53 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
| @@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/% | |||
| 75 | $(obj)/empty.c: | 76 | $(obj)/empty.c: |
| 76 | @touch $@ | 77 | @touch $@ |
| 77 | 78 | ||
| 78 | $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S | 79 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S |
| 79 | @cp $< $@ | 80 | @cp $< $@ |
| 80 | 81 | ||
| 81 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ | 82 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ |
| 82 | empty.c zImage.coff.lds zImage.lds | 83 | empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds |
| 83 | 84 | ||
| 84 | quiet_cmd_bootcc = BOOTCC $@ | 85 | quiet_cmd_bootcc = BOOTCC $@ |
| 85 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< | 86 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< |
| @@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree | |||
| 102 | 103 | ||
| 103 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) | 104 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) |
| 104 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | 105 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ |
| 105 | $(obj)/zImage.lds $(obj)/zImage.coff.lds | 106 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds |
| 106 | 107 | ||
| 107 | wrapper :=$(srctree)/$(src)/wrapper | 108 | wrapper :=$(srctree)/$(src)/wrapper |
| 108 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ | 109 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ |
| @@ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries | |||
| 132 | image-$(CONFIG_PPC_CHRP) += zImage.chrp | 133 | image-$(CONFIG_PPC_CHRP) += zImage.chrp |
| 133 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp | 134 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp |
| 134 | image-$(CONFIG_PPC_PMAC) += zImage.pmac | 135 | image-$(CONFIG_PPC_PMAC) += zImage.pmac |
| 135 | image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf | 136 | image-$(CONFIG_PPC_HOLLY) += zImage.holly |
| 136 | image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 | 137 | image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 |
| 137 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries | 138 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries |
| 138 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage | 139 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage |
| @@ -157,55 +158,43 @@ targets += $(image-y) $(initrd-y) | |||
| 157 | 158 | ||
| 158 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz | 159 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz |
| 159 | 160 | ||
| 160 | dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-)) | 161 | # If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an |
| 161 | dts-y := $(patsubst zImage%, zImage.dts%, $(image-y)) | 162 | # empty string, define 'dts' to be path to the dts |
| 162 | dts-y := $(filter-out $(image-y), $(dts-y)) | 163 | # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them |
| 163 | targets += $(image-y) $(dts-y) | 164 | ifeq ($(CONFIG_WANT_DEVICE_TREE),y) |
| 164 | 165 | ifneq ($(CONFIG_DEVICE_TREE),"") | |
| 165 | dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-)) | 166 | dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ |
| 166 | dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y)) | 167 | ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) |
| 167 | dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y)) | 168 | endif |
| 168 | targets += $(image-y) $(dts_initrd-y) | 169 | endif |
| 169 | |||
| 170 | $(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz | ||
| 171 | 170 | ||
| 172 | # Don't put the ramdisk on the pattern rule; when its missing make will try | 171 | # Don't put the ramdisk on the pattern rule; when its missing make will try |
| 173 | # the pattern rule with less dependencies that also matches (even with the | 172 | # the pattern rule with less dependencies that also matches (even with the |
| 174 | # hard dependency listed). | 173 | # hard dependency listed). |
| 175 | $(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz | 174 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts) |
| 176 | $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) | 175 | $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) |
| 177 | 176 | ||
| 178 | $(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts) | 177 | $(obj)/zImage.%: vmlinux $(wrapperbits) $(dts) |
| 179 | $(call if_changed,wrap,$*,$(dts)) | 178 | $(call if_changed,wrap,$*,$(dts)) |
| 180 | 179 | ||
| 181 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) | 180 | # This cannot be in the root of $(src) as the zImage rule always adds a $(obj) |
| 182 | $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) | 181 | # prefix |
| 183 | 182 | $(obj)/vmlinux.strip: vmlinux | |
| 184 | $(obj)/zImage.%: vmlinux $(wrapperbits) | ||
| 185 | $(call if_changed,wrap,$*) | ||
| 186 | |||
| 187 | $(obj)/zImage.iseries: vmlinux | ||
| 188 | $(STRIP) -s -R .comment $< -o $@ | 183 | $(STRIP) -s -R .comment $< -o $@ |
| 189 | 184 | ||
| 190 | $(obj)/zImage.ps3: vmlinux | 185 | $(obj)/zImage.iseries: vmlinux |
| 191 | $(STRIP) -s -R .comment $< -o $@ | 186 | $(STRIP) -s -R .comment $< -o $@ |
| 192 | 187 | ||
| 193 | $(obj)/zImage.initrd.ps3: vmlinux | 188 | $(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts |
| 194 | @echo " WARNING zImage.initrd.ps3 not supported (yet)" | 189 | $(STRIP) -s -R .comment $< -o vmlinux.strip |
| 195 | 190 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,) | |
| 196 | $(obj)/zImage.holly-elf: vmlinux $(wrapperbits) | ||
| 197 | $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,) | ||
| 198 | 191 | ||
| 199 | $(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz | 192 | $(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz |
| 200 | $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz) | 193 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz) |
| 201 | 194 | ||
| 202 | $(obj)/uImage: vmlinux $(wrapperbits) | 195 | $(obj)/uImage: vmlinux $(wrapperbits) |
| 203 | $(call if_changed,wrap,uboot) | 196 | $(call if_changed,wrap,uboot) |
| 204 | 197 | ||
| 205 | # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them | ||
| 206 | dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ | ||
| 207 | ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) | ||
| 208 | |||
| 209 | $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) | 198 | $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) |
| 210 | $(call if_changed,wrap,cuboot-$*,$(dts)) | 199 | $(call if_changed,wrap,cuboot-$*,$(dts)) |
| 211 | 200 | ||
| @@ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits) | |||
| 215 | $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) | 204 | $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) |
| 216 | $(call if_changed,wrap,treeboot-$*,$(dts)) | 205 | $(call if_changed,wrap,treeboot-$*,$(dts)) |
| 217 | 206 | ||
| 207 | # If there isn't a platform selected then just strip the vmlinux. | ||
| 208 | ifeq (,$(image-y)) | ||
| 209 | image-y := vmlinux.strip | ||
| 210 | endif | ||
| 211 | |||
| 218 | $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) | 212 | $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) |
| 219 | @rm -f $@; ln $< $@ | 213 | @rm -f $@; ln $< $@ |
| 220 | $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) | 214 | $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) |
| 221 | @rm -f $@; ln $< $@ | 215 | @rm -f $@; ln $< $@ |
| 222 | $(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y)) | ||
| 223 | @rm -f $@; ln $< $@ | ||
| 224 | $(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y)) | ||
| 225 | @rm -f $@; ln $< $@ | ||
| 226 | |||
| 227 | 216 | ||
| 228 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) | 217 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) |
| 229 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< | 218 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< |
| 230 | 219 | ||
| 231 | # anything not in $(targets) | 220 | # anything not in $(targets) |
| 232 | clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \ | 221 | clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ |
| 233 | treeImage.* zImage.dts zImage.dts_initrd | 222 | otheros.bld |
| 234 | 223 | ||
| 235 | # clean up files cached by wrapper | 224 | # clean up files cached by wrapper |
| 236 | clean-kernel := vmlinux.strip vmlinux.bin | 225 | clean-kernel := vmlinux.strip vmlinux.bin |
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c index 9af554eea54b..296025d8b295 100644 --- a/arch/powerpc/boot/cuboot-83xx.c +++ b/arch/powerpc/boot/cuboot-83xx.c | |||
| @@ -12,12 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | #include "ops.h" | 13 | #include "ops.h" |
| 14 | #include "stdio.h" | 14 | #include "stdio.h" |
| 15 | #include "cuboot.h" | ||
| 15 | 16 | ||
| 16 | #define TARGET_83xx | 17 | #define TARGET_83xx |
| 17 | #include "ppcboot.h" | 18 | #include "ppcboot.h" |
| 18 | 19 | ||
| 19 | static bd_t bd; | 20 | static bd_t bd; |
| 20 | extern char _end[]; | ||
| 21 | extern char _dtb_start[], _dtb_end[]; | 21 | extern char _dtb_start[], _dtb_end[]; |
| 22 | 22 | ||
| 23 | static void platform_fixups(void) | 23 | static void platform_fixups(void) |
| @@ -52,16 +52,7 @@ static void platform_fixups(void) | |||
| 52 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 52 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
| 53 | unsigned long r6, unsigned long r7) | 53 | unsigned long r6, unsigned long r7) |
| 54 | { | 54 | { |
| 55 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 55 | CUBOOT_INIT(); |
| 56 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
| 57 | |||
| 58 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
| 59 | loader_info.initrd_addr = r4; | ||
| 60 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
| 61 | loader_info.cmdline = (char *)r6; | ||
| 62 | loader_info.cmdline_len = r7 - r6; | ||
| 63 | |||
| 64 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
| 65 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 56 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
| 66 | serial_console_init(); | 57 | serial_console_init(); |
| 67 | platform_ops.fixups = platform_fixups; | 58 | platform_ops.fixups = platform_fixups; |
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c index e2560317f278..10f0f697c935 100644 --- a/arch/powerpc/boot/cuboot-85xx.c +++ b/arch/powerpc/boot/cuboot-85xx.c | |||
| @@ -12,12 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | #include "ops.h" | 13 | #include "ops.h" |
| 14 | #include "stdio.h" | 14 | #include "stdio.h" |
| 15 | #include "cuboot.h" | ||
| 15 | 16 | ||
| 16 | #define TARGET_85xx | 17 | #define TARGET_85xx |
| 17 | #include "ppcboot.h" | 18 | #include "ppcboot.h" |
| 18 | 19 | ||
| 19 | static bd_t bd; | 20 | static bd_t bd; |
| 20 | extern char _end[]; | ||
| 21 | extern char _dtb_start[], _dtb_end[]; | 21 | extern char _dtb_start[], _dtb_end[]; |
| 22 | 22 | ||
| 23 | static void platform_fixups(void) | 23 | static void platform_fixups(void) |
| @@ -53,16 +53,7 @@ static void platform_fixups(void) | |||
| 53 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 53 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
| 54 | unsigned long r6, unsigned long r7) | 54 | unsigned long r6, unsigned long r7) |
| 55 | { | 55 | { |
| 56 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 56 | CUBOOT_INIT(); |
| 57 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
| 58 | |||
| 59 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
| 60 | loader_info.initrd_addr = r4; | ||
| 61 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
| 62 | loader_info.cmdline = (char *)r6; | ||
| 63 | loader_info.cmdline_len = r7 - r6; | ||
| 64 | |||
| 65 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
| 66 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 57 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
| 67 | serial_console_init(); | 58 | serial_console_init(); |
| 68 | platform_ops.fixups = platform_fixups; | 59 | platform_ops.fixups = platform_fixups; |
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c index 4464c5f67acb..c5f37ce172ea 100644 --- a/arch/powerpc/boot/cuboot-ebony.c +++ b/arch/powerpc/boot/cuboot-ebony.c | |||
| @@ -15,28 +15,16 @@ | |||
| 15 | #include "ops.h" | 15 | #include "ops.h" |
| 16 | #include "stdio.h" | 16 | #include "stdio.h" |
| 17 | #include "44x.h" | 17 | #include "44x.h" |
| 18 | #include "cuboot.h" | ||
| 18 | 19 | ||
| 19 | #define TARGET_44x | 20 | #define TARGET_44x |
| 20 | #include "ppcboot.h" | 21 | #include "ppcboot.h" |
| 21 | 22 | ||
| 22 | static bd_t bd; | 23 | static bd_t bd; |
| 23 | extern char _end[]; | ||
| 24 | |||
| 25 | BSS_STACK(4096); | ||
| 26 | 24 | ||
| 27 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 25 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
| 28 | unsigned long r6, unsigned long r7) | 26 | unsigned long r6, unsigned long r7) |
| 29 | { | 27 | { |
| 30 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 28 | CUBOOT_INIT(); |
| 31 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
| 32 | |||
| 33 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
| 34 | loader_info.initrd_addr = r4; | ||
| 35 | loader_info.initrd_size = r4 ? r5 : 0; | ||
| 36 | loader_info.cmdline = (char *)r6; | ||
| 37 | loader_info.cmdline_len = r7 - r6; | ||
| 38 | |||
| 39 | simple_alloc_init(_end, avail_ram, 32, 64); | ||
| 40 | |||
| 41 | ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); | 29 | ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); |
| 42 | } | 30 | } |
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c new file mode 100644 index 000000000000..65795468ad6f --- /dev/null +++ b/arch/powerpc/boot/cuboot.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* | ||
| 2 | * Compatibility for old (not device tree aware) U-Boot versions | ||
| 3 | * | ||
| 4 | * Author: Scott Wood <scottwood@freescale.com> | ||
| 5 | * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au> | ||
| 6 | * | ||
| 7 | * Copyright 2007 David Gibson, IBM Corporation. | ||
| 8 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License version 2 as published | ||
| 12 | * by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "ops.h" | ||
| 16 | #include "stdio.h" | ||
| 17 | |||
| 18 | #include "ppcboot.h" | ||
| 19 | |||
| 20 | extern char _end[]; | ||
| 21 | extern char _dtb_start[], _dtb_end[]; | ||
| 22 | |||
| 23 | void cuboot_init(unsigned long r4, unsigned long r5, | ||
| 24 | unsigned long r6, unsigned long r7, | ||
| 25 | unsigned long end_of_ram) | ||
| 26 | { | ||
| 27 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
| 28 | |||
| 29 | loader_info.initrd_addr = r4; | ||
| 30 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
| 31 | loader_info.cmdline = (char *)r6; | ||
| 32 | loader_info.cmdline_len = r7 - r6; | ||
| 33 | |||
| 34 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
| 35 | } | ||
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h new file mode 100644 index 000000000000..cd2aa7f348f3 --- /dev/null +++ b/arch/powerpc/boot/cuboot.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #ifndef _PPC_BOOT_CUBOOT_H_ | ||
| 2 | #define _PPC_BOOT_CUBOOT_H_ | ||
| 3 | |||
| 4 | void cuboot_init(unsigned long r4, unsigned long r5, | ||
| 5 | unsigned long r6, unsigned long r7, | ||
| 6 | unsigned long end_of_ram); | ||
| 7 | |||
| 8 | #define CUBOOT_INIT() \ | ||
| 9 | do { \ | ||
| 10 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); \ | ||
| 11 | cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \ | ||
| 12 | } while (0) | ||
| 13 | |||
| 14 | #endif /* _PPC_BOOT_CUBOOT_H_ */ | ||
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h index 877bc97b1e97..14b44aa96fea 100644 --- a/arch/powerpc/boot/dcr.h +++ b/arch/powerpc/boot/dcr.h | |||
| @@ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C | |||
| 26 | #define SDRAM_CONFIG_BANK_SIZE(reg) \ | 26 | #define SDRAM_CONFIG_BANK_SIZE(reg) \ |
| 27 | (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) | 27 | (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) |
| 28 | 28 | ||
| 29 | /* 440GP External Bus Controller (EBC) */ | ||
| 30 | #define DCRN_EBC0_CFGADDR 0x012 | ||
| 31 | #define DCRN_EBC0_CFGDATA 0x013 | ||
| 32 | #define EBC_NUM_BANKS 8 | ||
| 33 | #define EBC_B0CR 0x00 | ||
| 34 | #define EBC_B1CR 0x01 | ||
| 35 | #define EBC_B2CR 0x02 | ||
| 36 | #define EBC_B3CR 0x03 | ||
| 37 | #define EBC_B4CR 0x04 | ||
| 38 | #define EBC_B5CR 0x05 | ||
| 39 | #define EBC_B6CR 0x06 | ||
| 40 | #define EBC_B7CR 0x07 | ||
| 41 | #define EBC_BXCR(n) (n) | ||
| 42 | #define EBC_BXCR_BAS 0xfff00000 | ||
| 43 | #define EBC_BXCR_BS 0x000e0000 | ||
| 44 | #define EBC_BXCR_BANK_SIZE(reg) \ | ||
| 45 | (0x100000 << (((reg) & EBC_BXCR_BS) >> 17)) | ||
| 46 | #define EBC_BXCR_BU 0x00018000 | ||
| 47 | #define EBC_BXCR_BU_OFF 0x00000000 | ||
| 48 | #define EBC_BXCR_BU_RO 0x00008000 | ||
| 49 | #define EBC_BXCR_BU_WO 0x00010000 | ||
| 50 | #define EBC_BXCR_BU_RW 0x00018000 | ||
| 51 | #define EBC_BXCR_BW 0x00006000 | ||
| 52 | #define EBC_B0AP 0x10 | ||
| 53 | #define EBC_B1AP 0x11 | ||
| 54 | #define EBC_B2AP 0x12 | ||
| 55 | #define EBC_B3AP 0x13 | ||
| 56 | #define EBC_B4AP 0x14 | ||
| 57 | #define EBC_B5AP 0x15 | ||
| 58 | #define EBC_B6AP 0x16 | ||
| 59 | #define EBC_B7AP 0x17 | ||
| 60 | #define EBC_BXAP(n) (0x10+(n)) | ||
| 61 | #define EBC_BEAR 0x20 | ||
| 62 | #define EBC_BESR 0x21 | ||
| 63 | #define EBC_CFG 0x23 | ||
| 64 | #define EBC_CID 0x24 | ||
| 65 | |||
| 29 | /* 440GP Clock, PM, chip control */ | 66 | /* 440GP Clock, PM, chip control */ |
| 30 | #define DCRN_CPC0_SR 0x0b0 | 67 | #define DCRN_CPC0_SR 0x0b0 |
| 31 | #define DCRN_CPC0_ER 0x0b1 | 68 | #define DCRN_CPC0_ER 0x0b1 |
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts index 0ec02f4726b5..c5f99613fc7b 100644 --- a/arch/powerpc/boot/dts/ebony.dts +++ b/arch/powerpc/boot/dts/ebony.dts | |||
| @@ -31,8 +31,8 @@ | |||
| 31 | reg = <0>; | 31 | reg = <0>; |
| 32 | clock-frequency = <0>; // Filled in by zImage | 32 | clock-frequency = <0>; // Filled in by zImage |
| 33 | timebase-frequency = <0>; // Filled in by zImage | 33 | timebase-frequency = <0>; // Filled in by zImage |
| 34 | i-cache-line-size = <32>; | 34 | i-cache-line-size = <20>; |
| 35 | d-cache-line-size = <32>; | 35 | d-cache-line-size = <20>; |
| 36 | i-cache-size = <8000>; /* 32 kB */ | 36 | i-cache-size = <8000>; /* 32 kB */ |
| 37 | d-cache-size = <8000>; /* 32 kB */ | 37 | d-cache-size = <8000>; /* 32 kB */ |
| 38 | dcr-controller; | 38 | dcr-controller; |
| @@ -135,11 +135,9 @@ | |||
| 135 | #address-cells = <2>; | 135 | #address-cells = <2>; |
| 136 | #size-cells = <1>; | 136 | #size-cells = <1>; |
| 137 | clock-frequency = <0>; // Filled in by zImage | 137 | clock-frequency = <0>; // Filled in by zImage |
| 138 | ranges = <0 00000000 fff00000 100000 | 138 | // ranges property is supplied by zImage |
| 139 | 1 00000000 48000000 100000 | 139 | // based on firmware's configuration of the |
| 140 | 2 00000000 ff800000 400000 | 140 | // EBC bridge |
| 141 | 3 00000000 48200000 100000 | ||
| 142 | 7 00000000 48300000 100000>; | ||
| 143 | interrupts = <5 4>; | 141 | interrupts = <5 4>; |
| 144 | interrupt-parent = <&UIC1>; | 142 | interrupt-parent = <&UIC1>; |
| 145 | 143 | ||
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts index 254499b107f4..80a4fab8ee37 100644 --- a/arch/powerpc/boot/dts/holly.dts +++ b/arch/powerpc/boot/dts/holly.dts | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | tsi109@c0000000 { | 47 | tsi109@c0000000 { |
| 48 | device_type = "tsi-bridge"; | 48 | device_type = "tsi-bridge"; |
| 49 | compatible = "tsi-bridge"; | 49 | compatible = "tsi109-bridge", "tsi108-bridge"; |
| 50 | #address-cells = <1>; | 50 | #address-cells = <1>; |
| 51 | #size-cells = <1>; | 51 | #size-cells = <1>; |
| 52 | ranges = <00000000 c0000000 00010000>; | 52 | ranges = <00000000 c0000000 00010000>; |
| @@ -54,52 +54,55 @@ | |||
| 54 | 54 | ||
| 55 | i2c@7000 { | 55 | i2c@7000 { |
| 56 | device_type = "i2c"; | 56 | device_type = "i2c"; |
| 57 | compatible = "tsi-i2c"; | 57 | compatible = "tsi109-i2c", "tsi108-i2c"; |
| 58 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 58 | interrupt-parent = <&MPIC>; |
| 59 | interrupts = <e 2>; | 59 | interrupts = <e 2>; |
| 60 | reg = <7000 400>; | 60 | reg = <7000 400>; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | mdio@6000 { | 63 | MDIO: mdio@6000 { |
| 64 | device_type = "mdio"; | 64 | device_type = "mdio"; |
| 65 | compatible = "tsi-ethernet"; | 65 | compatible = "tsi109-mdio", "tsi108-mdio"; |
| 66 | reg = <6000 50>; | ||
| 67 | #address-cells = <1>; | ||
| 68 | #size-cells = <0>; | ||
| 66 | 69 | ||
| 67 | PHY1: ethernet-phy@6000 { | 70 | PHY1: ethernet-phy@1 { |
| 68 | device_type = "ethernet-phy"; | 71 | compatible = "bcm5461a"; |
| 69 | compatible = "bcm54xx"; | 72 | reg = <1>; |
| 70 | reg = <6000 50>; | 73 | txc-rxc-delay-disable; |
| 71 | phy-id = <1>; | ||
| 72 | }; | 74 | }; |
| 73 | 75 | ||
| 74 | PHY2: ethernet-phy@6400 { | 76 | PHY2: ethernet-phy@2 { |
| 75 | device_type = "ethernet-phy"; | 77 | compatible = "bcm5461a"; |
| 76 | compatible = "bcm54xx"; | 78 | reg = <2>; |
| 77 | reg = <6000 50>; | 79 | txc-rxc-delay-disable; |
| 78 | phy-id = <2>; | ||
| 79 | }; | 80 | }; |
| 80 | }; | 81 | }; |
| 81 | 82 | ||
| 82 | ethernet@6200 { | 83 | ethernet@6200 { |
| 83 | device_type = "network"; | 84 | device_type = "network"; |
| 84 | compatible = "tsi-ethernet"; | 85 | compatible = "tsi109-ethernet", "tsi108-ethernet"; |
| 85 | #address-cells = <1>; | 86 | #address-cells = <1>; |
| 86 | #size-cells = <0>; | 87 | #size-cells = <0>; |
| 87 | reg = <6000 200>; | 88 | reg = <6000 200>; |
| 88 | local-mac-address = [ 00 00 00 00 00 00 ]; | 89 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 89 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 90 | interrupt-parent = <&MPIC>; |
| 90 | interrupts = <10 2>; | 91 | interrupts = <10 2>; |
| 92 | mdio-handle = <&MDIO>; | ||
| 91 | phy-handle = <&PHY1>; | 93 | phy-handle = <&PHY1>; |
| 92 | }; | 94 | }; |
| 93 | 95 | ||
| 94 | ethernet@6600 { | 96 | ethernet@6600 { |
| 95 | device_type = "network"; | 97 | device_type = "network"; |
| 96 | compatible = "tsi-ethernet"; | 98 | compatible = "tsi109-ethernet", "tsi108-ethernet"; |
| 97 | #address-cells = <1>; | 99 | #address-cells = <1>; |
| 98 | #size-cells = <0>; | 100 | #size-cells = <0>; |
| 99 | reg = <6400 200>; | 101 | reg = <6400 200>; |
| 100 | local-mac-address = [ 00 00 00 00 00 00 ]; | 102 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 101 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 103 | interrupt-parent = <&MPIC>; |
| 102 | interrupts = <11 2>; | 104 | interrupts = <11 2>; |
| 105 | mdio-handle = <&MDIO>; | ||
| 103 | phy-handle = <&PHY2>; | 106 | phy-handle = <&PHY2>; |
| 104 | }; | 107 | }; |
| 105 | 108 | ||
| @@ -110,7 +113,7 @@ | |||
| 110 | virtual-reg = <c0007808>; | 113 | virtual-reg = <c0007808>; |
| 111 | clock-frequency = <3F9C6000>; | 114 | clock-frequency = <3F9C6000>; |
| 112 | current-speed = <1c200>; | 115 | current-speed = <1c200>; |
| 113 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 116 | interrupt-parent = <&MPIC>; |
| 114 | interrupts = <c 2>; | 117 | interrupts = <c 2>; |
| 115 | }; | 118 | }; |
| 116 | 119 | ||
| @@ -121,7 +124,7 @@ | |||
| 121 | virtual-reg = <c0007c08>; | 124 | virtual-reg = <c0007c08>; |
| 122 | clock-frequency = <3F9C6000>; | 125 | clock-frequency = <3F9C6000>; |
| 123 | current-speed = <1c200>; | 126 | current-speed = <1c200>; |
| 124 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 127 | interrupt-parent = <&MPIC>; |
| 125 | interrupts = <d 2>; | 128 | interrupts = <d 2>; |
| 126 | }; | 129 | }; |
| 127 | 130 | ||
| @@ -136,7 +139,7 @@ | |||
| 136 | 139 | ||
| 137 | pci@1000 { | 140 | pci@1000 { |
| 138 | device_type = "pci"; | 141 | device_type = "pci"; |
| 139 | compatible = "tsi109"; | 142 | compatible = "tsi109-pci", "tsi108-pci"; |
| 140 | #interrupt-cells = <1>; | 143 | #interrupt-cells = <1>; |
| 141 | #size-cells = <2>; | 144 | #size-cells = <2>; |
| 142 | #address-cells = <3>; | 145 | #address-cells = <3>; |
| @@ -150,7 +153,7 @@ | |||
| 150 | ranges = <02000000 0 40000000 40000000 0 10000000 | 153 | ranges = <02000000 0 40000000 40000000 0 10000000 |
| 151 | 01000000 0 00000000 7e000000 0 00010000>; | 154 | 01000000 0 00000000 7e000000 0 00010000>; |
| 152 | clock-frequency = <7f28154>; | 155 | clock-frequency = <7f28154>; |
| 153 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 156 | interrupt-parent = <&MPIC>; |
| 154 | interrupts = <17 2>; | 157 | interrupts = <17 2>; |
| 155 | interrupt-map-mask = <f800 0 0 7>; | 158 | interrupt-map-mask = <f800 0 0 7>; |
| 156 | /*----------------------------------------------------+ | 159 | /*----------------------------------------------------+ |
| @@ -186,13 +189,12 @@ | |||
| 186 | #address-cells = <0>; | 189 | #address-cells = <0>; |
| 187 | #interrupt-cells = <2>; | 190 | #interrupt-cells = <2>; |
| 188 | interrupts = <17 2>; | 191 | interrupts = <17 2>; |
| 189 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 192 | interrupt-parent = <&MPIC>; |
| 190 | }; | 193 | }; |
| 191 | }; | 194 | }; |
| 192 | }; | 195 | }; |
| 193 | 196 | ||
| 194 | chosen { | 197 | chosen { |
| 195 | linux,stdout-path = "/tsi109@c0000000/serial@7808"; | 198 | linux,stdout-path = "/tsi109@c0000000/serial@7808"; |
| 196 | bootargs = "console=ttyS0,115200"; | ||
| 197 | }; | 199 | }; |
| 198 | }; | 200 | }; |
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts index 765c306ecf80..0e3d314a7158 100644 --- a/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | #address-cells = <1>; | 45 | #address-cells = <1>; |
| 46 | #size-cells = <1>; | 46 | #size-cells = <1>; |
| 47 | #interrupt-cells = <2>; | 47 | #interrupt-cells = <2>; |
| 48 | device_type = "tsi-bridge"; | 48 | device_type = "tsi108-bridge"; |
| 49 | ranges = <00000000 c0000000 00010000>; | 49 | ranges = <00000000 c0000000 00010000>; |
| 50 | reg = <c0000000 00010000>; | 50 | reg = <c0000000 00010000>; |
| 51 | bus-frequency = <0>; | 51 | bus-frequency = <0>; |
| @@ -55,27 +55,26 @@ | |||
| 55 | interrupts = <E 0>; | 55 | interrupts = <E 0>; |
| 56 | reg = <7000 400>; | 56 | reg = <7000 400>; |
| 57 | device_type = "i2c"; | 57 | device_type = "i2c"; |
| 58 | compatible = "tsi-i2c"; | 58 | compatible = "tsi108-i2c"; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | mdio@6000 { | 61 | MDIO: mdio@6000 { |
| 62 | device_type = "mdio"; | 62 | device_type = "mdio"; |
| 63 | compatible = "tsi-ethernet"; | 63 | compatible = "tsi108-mdio"; |
| 64 | reg = <6000 50>; | ||
| 65 | #address-cells = <1>; | ||
| 66 | #size-cells = <0>; | ||
| 64 | 67 | ||
| 65 | phy8: ethernet-phy@6000 { | 68 | phy8: ethernet-phy@8 { |
| 66 | interrupt-parent = <&mpic>; | 69 | interrupt-parent = <&mpic>; |
| 67 | interrupts = <2 1>; | 70 | interrupts = <2 1>; |
| 68 | reg = <6000 50>; | 71 | reg = <8>; |
| 69 | phy-id = <8>; | ||
| 70 | device_type = "ethernet-phy"; | ||
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | phy9: ethernet-phy@6400 { | 74 | phy9: ethernet-phy@9 { |
| 74 | interrupt-parent = <&mpic>; | 75 | interrupt-parent = <&mpic>; |
| 75 | interrupts = <2 1>; | 76 | interrupts = <2 1>; |
| 76 | reg = <6000 50>; | 77 | reg = <9>; |
| 77 | phy-id = <9>; | ||
| 78 | device_type = "ethernet-phy"; | ||
| 79 | }; | 78 | }; |
| 80 | 79 | ||
| 81 | }; | 80 | }; |
| @@ -83,12 +82,12 @@ | |||
| 83 | ethernet@6200 { | 82 | ethernet@6200 { |
| 84 | #size-cells = <0>; | 83 | #size-cells = <0>; |
| 85 | device_type = "network"; | 84 | device_type = "network"; |
| 86 | model = "TSI-ETH"; | 85 | compatible = "tsi108-ethernet"; |
| 87 | compatible = "tsi-ethernet"; | ||
| 88 | reg = <6000 200>; | 86 | reg = <6000 200>; |
| 89 | address = [ 00 06 D2 00 00 01 ]; | 87 | address = [ 00 06 D2 00 00 01 ]; |
| 90 | interrupts = <10 2>; | 88 | interrupts = <10 2>; |
| 91 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | mdio-handle = <&MDIO>; | ||
| 92 | phy-handle = <&phy8>; | 91 | phy-handle = <&phy8>; |
| 93 | }; | 92 | }; |
| 94 | 93 | ||
| @@ -96,12 +95,12 @@ | |||
| 96 | #address-cells = <1>; | 95 | #address-cells = <1>; |
| 97 | #size-cells = <0>; | 96 | #size-cells = <0>; |
| 98 | device_type = "network"; | 97 | device_type = "network"; |
| 99 | model = "TSI-ETH"; | 98 | compatible = "tsi108-ethernet"; |
| 100 | compatible = "tsi-ethernet"; | ||
| 101 | reg = <6400 200>; | 99 | reg = <6400 200>; |
| 102 | address = [ 00 06 D2 00 00 02 ]; | 100 | address = [ 00 06 D2 00 00 02 ]; |
| 103 | interrupts = <11 2>; | 101 | interrupts = <11 2>; |
| 104 | interrupt-parent = <&mpic>; | 102 | interrupt-parent = <&mpic>; |
| 103 | mdio-handle = <&MDIO>; | ||
| 105 | phy-handle = <&phy9>; | 104 | phy-handle = <&phy9>; |
| 106 | }; | 105 | }; |
| 107 | 106 | ||
| @@ -135,7 +134,7 @@ | |||
| 135 | big-endian; | 134 | big-endian; |
| 136 | }; | 135 | }; |
| 137 | pci@1000 { | 136 | pci@1000 { |
| 138 | compatible = "tsi10x"; | 137 | compatible = "tsi108-pci"; |
| 139 | device_type = "pci"; | 138 | device_type = "pci"; |
| 140 | #interrupt-cells = <1>; | 139 | #interrupt-cells = <1>; |
| 141 | #size-cells = <2>; | 140 | #size-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts index 423eedcf634f..1934b800278e 100644 --- a/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/arch/powerpc/boot/dts/mpc8272ads.dts | |||
| @@ -14,12 +14,10 @@ | |||
| 14 | compatible = "MPC8260ADS"; | 14 | compatible = "MPC8260ADS"; |
| 15 | #address-cells = <1>; | 15 | #address-cells = <1>; |
| 16 | #size-cells = <1>; | 16 | #size-cells = <1>; |
| 17 | linux,phandle = <100>; | ||
| 18 | 17 | ||
| 19 | cpus { | 18 | cpus { |
| 20 | #address-cells = <1>; | 19 | #address-cells = <1>; |
| 21 | #size-cells = <0>; | 20 | #size-cells = <0>; |
| 22 | linux,phandle = <200>; | ||
| 23 | 21 | ||
| 24 | PowerPC,8272@0 { | 22 | PowerPC,8272@0 { |
| 25 | device_type = "cpu"; | 23 | device_type = "cpu"; |
| @@ -32,12 +30,10 @@ | |||
| 32 | bus-frequency = <0>; | 30 | bus-frequency = <0>; |
| 33 | clock-frequency = <0>; | 31 | clock-frequency = <0>; |
| 34 | 32-bit; | 32 | 32-bit; |
| 35 | linux,phandle = <201>; | ||
| 36 | }; | 33 | }; |
| 37 | }; | 34 | }; |
| 38 | 35 | ||
| 39 | interrupt-controller@f8200000 { | 36 | pci_pic: interrupt-controller@f8200000 { |
| 40 | linux,phandle = <f8200000>; | ||
| 41 | #address-cells = <0>; | 37 | #address-cells = <0>; |
| 42 | #interrupt-cells = <2>; | 38 | #interrupt-cells = <2>; |
| 43 | interrupt-controller; | 39 | interrupt-controller; |
| @@ -47,15 +43,13 @@ | |||
| 47 | }; | 43 | }; |
| 48 | memory { | 44 | memory { |
| 49 | device_type = "memory"; | 45 | device_type = "memory"; |
| 50 | linux,phandle = <300>; | ||
| 51 | reg = <00000000 4000000 f4500000 00000020>; | 46 | reg = <00000000 4000000 f4500000 00000020>; |
| 52 | }; | 47 | }; |
| 53 | 48 | ||
| 54 | chosen { | 49 | chosen { |
| 55 | name = "chosen"; | 50 | name = "chosen"; |
| 56 | linux,platform = <0>; | 51 | linux,platform = <0>; |
| 57 | interrupt-controller = <10c00>; | 52 | interrupt-controller = <&Cpm_pic>; |
| 58 | linux,phandle = <400>; | ||
| 59 | }; | 53 | }; |
| 60 | 54 | ||
| 61 | soc8272@f0000000 { | 55 | soc8272@f0000000 { |
| @@ -70,20 +64,17 @@ | |||
| 70 | device_type = "mdio"; | 64 | device_type = "mdio"; |
| 71 | compatible = "fs_enet"; | 65 | compatible = "fs_enet"; |
| 72 | reg = <0 0>; | 66 | reg = <0 0>; |
| 73 | linux,phandle = <24520>; | ||
| 74 | #address-cells = <1>; | 67 | #address-cells = <1>; |
| 75 | #size-cells = <0>; | 68 | #size-cells = <0>; |
| 76 | ethernet-phy@0 { | 69 | phy0:ethernet-phy@0 { |
| 77 | linux,phandle = <2452000>; | 70 | interrupt-parent = <&Cpm_pic>; |
| 78 | interrupt-parent = <10c00>; | ||
| 79 | interrupts = <17 4>; | 71 | interrupts = <17 4>; |
| 80 | reg = <0>; | 72 | reg = <0>; |
| 81 | bitbang = [ 12 12 13 02 02 01 ]; | 73 | bitbang = [ 12 12 13 02 02 01 ]; |
| 82 | device_type = "ethernet-phy"; | 74 | device_type = "ethernet-phy"; |
| 83 | }; | 75 | }; |
| 84 | ethernet-phy@1 { | 76 | phy1:ethernet-phy@1 { |
| 85 | linux,phandle = <2452001>; | 77 | interrupt-parent = <&Cpm_pic>; |
| 86 | interrupt-parent = <10c00>; | ||
| 87 | interrupts = <17 4>; | 78 | interrupts = <17 4>; |
| 88 | bitbang = [ 12 12 13 02 02 01 ]; | 79 | bitbang = [ 12 12 13 02 02 01 ]; |
| 89 | reg = <3>; | 80 | reg = <3>; |
| @@ -101,8 +92,8 @@ | |||
| 101 | reg = <11300 20 8400 100 11380 30>; | 92 | reg = <11300 20 8400 100 11380 30>; |
| 102 | mac-address = [ 00 11 2F 99 43 54 ]; | 93 | mac-address = [ 00 11 2F 99 43 54 ]; |
| 103 | interrupts = <20 2>; | 94 | interrupts = <20 2>; |
| 104 | interrupt-parent = <10c00>; | 95 | interrupt-parent = <&Cpm_pic>; |
| 105 | phy-handle = <2452000>; | 96 | phy-handle = <&Phy0>; |
| 106 | rx-clock = <13>; | 97 | rx-clock = <13>; |
| 107 | tx-clock = <12>; | 98 | tx-clock = <12>; |
| 108 | }; | 99 | }; |
| @@ -115,14 +106,13 @@ | |||
| 115 | reg = <11320 20 8500 100 113b0 30>; | 106 | reg = <11320 20 8500 100 113b0 30>; |
| 116 | mac-address = [ 00 11 2F 99 44 54 ]; | 107 | mac-address = [ 00 11 2F 99 44 54 ]; |
| 117 | interrupts = <21 2>; | 108 | interrupts = <21 2>; |
| 118 | interrupt-parent = <10c00>; | 109 | interrupt-parent = <&Cpm_pic>; |
| 119 | phy-handle = <2452001>; | 110 | phy-handle = <&Phy1>; |
| 120 | rx-clock = <17>; | 111 | rx-clock = <17>; |
| 121 | tx-clock = <18>; | 112 | tx-clock = <18>; |
| 122 | }; | 113 | }; |
| 123 | 114 | ||
| 124 | cpm@f0000000 { | 115 | cpm@f0000000 { |
| 125 | linux,phandle = <f0000000>; | ||
| 126 | #address-cells = <1>; | 116 | #address-cells = <1>; |
| 127 | #size-cells = <1>; | 117 | #size-cells = <1>; |
| 128 | #interrupt-cells = <2>; | 118 | #interrupt-cells = <2>; |
| @@ -142,7 +132,7 @@ | |||
| 142 | reg = <11a00 20 8000 100>; | 132 | reg = <11a00 20 8000 100>; |
| 143 | current-speed = <1c200>; | 133 | current-speed = <1c200>; |
| 144 | interrupts = <28 2>; | 134 | interrupts = <28 2>; |
| 145 | interrupt-parent = <10c00>; | 135 | interrupt-parent = <&Cpm_pic>; |
| 146 | clock-setup = <0 00ffffff>; | 136 | clock-setup = <0 00ffffff>; |
| 147 | rx-clock = <1>; | 137 | rx-clock = <1>; |
| 148 | tx-clock = <1>; | 138 | tx-clock = <1>; |
| @@ -156,15 +146,14 @@ | |||
| 156 | reg = <11a60 20 8300 100>; | 146 | reg = <11a60 20 8300 100>; |
| 157 | current-speed = <1c200>; | 147 | current-speed = <1c200>; |
| 158 | interrupts = <2b 2>; | 148 | interrupts = <2b 2>; |
| 159 | interrupt-parent = <10c00>; | 149 | interrupt-parent = <&Cpm_pic>; |
| 160 | clock-setup = <1b ffffff00>; | 150 | clock-setup = <1b ffffff00>; |
| 161 | rx-clock = <4>; | 151 | rx-clock = <4>; |
| 162 | tx-clock = <4>; | 152 | tx-clock = <4>; |
| 163 | }; | 153 | }; |
| 164 | 154 | ||
| 165 | }; | 155 | }; |
| 166 | interrupt-controller@10c00 { | 156 | cpm_pic:interrupt-controller@10c00 { |
| 167 | linux,phandle = <10c00>; | ||
| 168 | #address-cells = <0>; | 157 | #address-cells = <0>; |
| 169 | #interrupt-cells = <2>; | 158 | #interrupt-cells = <2>; |
| 170 | interrupt-controller; | 159 | interrupt-controller; |
| @@ -174,7 +163,6 @@ | |||
| 174 | compatible = "CPM2"; | 163 | compatible = "CPM2"; |
| 175 | }; | 164 | }; |
| 176 | pci@0500 { | 165 | pci@0500 { |
| 177 | linux,phandle = <0500>; | ||
| 178 | #interrupt-cells = <1>; | 166 | #interrupt-cells = <1>; |
| 179 | #size-cells = <2>; | 167 | #size-cells = <2>; |
| 180 | #address-cells = <3>; | 168 | #address-cells = <3>; |
| @@ -202,7 +190,7 @@ | |||
| 202 | c000 0 0 2 f8200000 43 8 | 190 | c000 0 0 2 f8200000 43 8 |
| 203 | c000 0 0 3 f8200000 40 8 | 191 | c000 0 0 3 f8200000 40 8 |
| 204 | c000 0 0 4 f8200000 41 8>; | 192 | c000 0 0 4 f8200000 41 8>; |
| 205 | interrupt-parent = <10c00>; | 193 | interrupt-parent = <&Cpm_pic>; |
| 206 | interrupts = <14 8>; | 194 | interrupts = <14 8>; |
| 207 | bus-range = <0 0>; | 195 | bus-range = <0 0>; |
| 208 | ranges = <02000000 0 80000000 80000000 0 40000000 | 196 | ranges = <02000000 0 80000000 80000000 0 40000000 |
| @@ -216,7 +204,7 @@ | |||
| 216 | compatible = "talitos"; | 204 | compatible = "talitos"; |
| 217 | reg = <30000 10000>; | 205 | reg = <30000 10000>; |
| 218 | interrupts = <b 2>; | 206 | interrupts = <b 2>; |
| 219 | interrupt-parent = <10c00>; | 207 | interrupt-parent = <&Cpm_pic>; |
| 220 | num-channels = <4>; | 208 | num-channels = <4>; |
| 221 | channel-fifo-len = <18>; | 209 | channel-fifo-len = <18>; |
| 222 | exec-units-mask = <0000007e>; | 210 | exec-units-mask = <0000007e>; |
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 112dd5198fe2..4fc0c4d34aa8 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts | |||
| @@ -272,7 +272,13 @@ | |||
| 272 | reg = <2200 200>; | 272 | reg = <2200 200>; |
| 273 | interrupts = <22>; | 273 | interrupts = <22>; |
| 274 | interrupt-parent = < &qeic >; | 274 | interrupt-parent = < &qeic >; |
| 275 | mac-address = [ 00 04 9f 00 23 23 ]; | 275 | /* |
| 276 | * mac-address is deprecated and will be removed | ||
| 277 | * in 2.6.25. Only recent versions of | ||
| 278 | * U-Boot support local-mac-address, however. | ||
| 279 | */ | ||
| 280 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 281 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 276 | rx-clock = <19>; | 282 | rx-clock = <19>; |
| 277 | tx-clock = <1a>; | 283 | tx-clock = <1a>; |
| 278 | phy-handle = < &phy3 >; | 284 | phy-handle = < &phy3 >; |
| @@ -287,7 +293,13 @@ | |||
| 287 | reg = <3000 200>; | 293 | reg = <3000 200>; |
| 288 | interrupts = <23>; | 294 | interrupts = <23>; |
| 289 | interrupt-parent = < &qeic >; | 295 | interrupt-parent = < &qeic >; |
| 290 | mac-address = [ 00 11 22 33 44 55 ]; | 296 | /* |
| 297 | * mac-address is deprecated and will be removed | ||
| 298 | * in 2.6.25. Only recent versions of | ||
| 299 | * U-Boot support local-mac-address, however. | ||
| 300 | */ | ||
| 301 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 302 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 291 | rx-clock = <17>; | 303 | rx-clock = <17>; |
| 292 | tx-clock = <18>; | 304 | tx-clock = <18>; |
| 293 | phy-handle = < &phy4 >; | 305 | phy-handle = < &phy4 >; |
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index be4c35784e49..447c03ffabbc 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts | |||
| @@ -231,7 +231,13 @@ | |||
| 231 | reg = <3000 200>; | 231 | reg = <3000 200>; |
| 232 | interrupts = <21>; | 232 | interrupts = <21>; |
| 233 | interrupt-parent = <&qeic>; | 233 | interrupt-parent = <&qeic>; |
| 234 | mac-address = [ 00 04 9f ef 03 02 ]; | 234 | /* |
| 235 | * mac-address is deprecated and will be removed | ||
| 236 | * in 2.6.25. Only recent versions of | ||
| 237 | * U-Boot support local-mac-address, however. | ||
| 238 | */ | ||
| 239 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 240 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 235 | rx-clock = <20>; | 241 | rx-clock = <20>; |
| 236 | tx-clock = <13>; | 242 | tx-clock = <13>; |
| 237 | phy-handle = <&phy00>; | 243 | phy-handle = <&phy00>; |
| @@ -246,7 +252,13 @@ | |||
| 246 | reg = <2200 200>; | 252 | reg = <2200 200>; |
| 247 | interrupts = <22>; | 253 | interrupts = <22>; |
| 248 | interrupt-parent = <&qeic>; | 254 | interrupt-parent = <&qeic>; |
| 249 | mac-address = [ 00 04 9f ef 03 01 ]; | 255 | /* |
| 256 | * mac-address is deprecated and will be removed | ||
| 257 | * in 2.6.25. Only recent versions of | ||
| 258 | * U-Boot support local-mac-address, however. | ||
| 259 | */ | ||
| 260 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 261 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 250 | rx-clock = <19>; | 262 | rx-clock = <19>; |
| 251 | tx-clock = <1a>; | 263 | tx-clock = <1a>; |
| 252 | phy-handle = <&phy04>; | 264 | phy-handle = <&phy04>; |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index db0d00303275..ae9bca575453 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
| @@ -131,6 +131,11 @@ | |||
| 131 | model = "TSEC"; | 131 | model = "TSEC"; |
| 132 | compatible = "gianfar"; | 132 | compatible = "gianfar"; |
| 133 | reg = <24000 1000>; | 133 | reg = <24000 1000>; |
| 134 | /* | ||
| 135 | * address is deprecated and will be removed | ||
| 136 | * in 2.6.25. Only recent versions of | ||
| 137 | * U-Boot support local-mac-address, however. | ||
| 138 | */ | ||
| 134 | address = [ 00 00 00 00 00 00 ]; | 139 | address = [ 00 00 00 00 00 00 ]; |
| 135 | local-mac-address = [ 00 00 00 00 00 00 ]; | 140 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 136 | interrupts = <20 8 21 8 22 8>; | 141 | interrupts = <20 8 21 8 22 8>; |
| @@ -145,6 +150,11 @@ | |||
| 145 | model = "TSEC"; | 150 | model = "TSEC"; |
| 146 | compatible = "gianfar"; | 151 | compatible = "gianfar"; |
| 147 | reg = <25000 1000>; | 152 | reg = <25000 1000>; |
| 153 | /* | ||
| 154 | * address is deprecated and will be removed | ||
| 155 | * in 2.6.25. Only recent versions of | ||
| 156 | * U-Boot support local-mac-address, however. | ||
| 157 | */ | ||
| 148 | address = [ 00 00 00 00 00 00 ]; | 158 | address = [ 00 00 00 00 00 00 ]; |
| 149 | local-mac-address = [ 00 00 00 00 00 00 ]; | 159 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 150 | interrupts = <23 8 24 8 25 8>; | 160 | interrupts = <23 8 24 8 25 8>; |
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index df773fafe9d1..310e877826b4 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts | |||
| @@ -136,6 +136,11 @@ | |||
| 136 | model = "TSEC"; | 136 | model = "TSEC"; |
| 137 | compatible = "gianfar"; | 137 | compatible = "gianfar"; |
| 138 | reg = <24000 1000>; | 138 | reg = <24000 1000>; |
| 139 | /* | ||
| 140 | * address is deprecated and will be removed | ||
| 141 | * in 2.6.25. Only recent versions of | ||
| 142 | * U-Boot support local-mac-address, however. | ||
| 143 | */ | ||
| 139 | address = [ 00 00 00 00 00 00 ]; | 144 | address = [ 00 00 00 00 00 00 ]; |
| 140 | local-mac-address = [ 00 00 00 00 00 00 ]; | 145 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 141 | interrupts = <20 8 21 8 22 8>; | 146 | interrupts = <20 8 21 8 22 8>; |
| @@ -150,6 +155,11 @@ | |||
| 150 | model = "TSEC"; | 155 | model = "TSEC"; |
| 151 | compatible = "gianfar"; | 156 | compatible = "gianfar"; |
| 152 | reg = <25000 1000>; | 157 | reg = <25000 1000>; |
| 158 | /* | ||
| 159 | * address is deprecated and will be removed | ||
| 160 | * in 2.6.25. Only recent versions of | ||
| 161 | * U-Boot support local-mac-address, however. | ||
| 162 | */ | ||
| 153 | address = [ 00 00 00 00 00 00 ]; | 163 | address = [ 00 00 00 00 00 00 ]; |
| 154 | local-mac-address = [ 00 00 00 00 00 00 ]; | 164 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 155 | interrupts = <23 8 24 8 25 8>; | 165 | interrupts = <23 8 24 8 25 8>; |
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 38c8594df3a4..1e914f31dd92 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts | |||
| @@ -301,7 +301,13 @@ | |||
| 301 | reg = <2000 200>; | 301 | reg = <2000 200>; |
| 302 | interrupts = <20>; | 302 | interrupts = <20>; |
| 303 | interrupt-parent = < &qeic >; | 303 | interrupt-parent = < &qeic >; |
| 304 | mac-address = [ 00 04 9f 00 23 23 ]; | 304 | /* |
| 305 | * mac-address is deprecated and will be removed | ||
| 306 | * in 2.6.25. Only recent versions of | ||
| 307 | * U-Boot support local-mac-address, however. | ||
| 308 | */ | ||
| 309 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 310 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 305 | rx-clock = <0>; | 311 | rx-clock = <0>; |
| 306 | tx-clock = <19>; | 312 | tx-clock = <19>; |
| 307 | phy-handle = < &phy0 >; | 313 | phy-handle = < &phy0 >; |
| @@ -317,7 +323,13 @@ | |||
| 317 | reg = <3000 200>; | 323 | reg = <3000 200>; |
| 318 | interrupts = <21>; | 324 | interrupts = <21>; |
| 319 | interrupt-parent = < &qeic >; | 325 | interrupt-parent = < &qeic >; |
| 320 | mac-address = [ 00 11 22 33 44 55 ]; | 326 | /* |
| 327 | * mac-address is deprecated and will be removed | ||
| 328 | * in 2.6.25. Only recent versions of | ||
| 329 | * U-Boot support local-mac-address, however. | ||
| 330 | */ | ||
| 331 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 332 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 321 | rx-clock = <0>; | 333 | rx-clock = <0>; |
| 322 | tx-clock = <14>; | 334 | tx-clock = <14>; |
| 323 | phy-handle = < &phy1 >; | 335 | phy-handle = < &phy1 >; |
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts index d91e81c009f5..364a969f5c2f 100644 --- a/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/arch/powerpc/boot/dts/mpc8540ads.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8540-memory-controller"; | 52 | compatible = "fsl,8540-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,14 +61,14 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | i2c@3000 { | 67 | i2c@3000 { |
| 68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
| 69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
| 70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
| 71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | dfsrr; | 73 | dfsrr; |
| 74 | }; | 74 | }; |
| @@ -81,19 +81,19 @@ | |||
| 81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
| 82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
| 83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
| 84 | interrupts = <35 1>; | 84 | interrupts = <5 1>; |
| 85 | reg = <0>; | 85 | reg = <0>; |
| 86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
| 87 | }; | 87 | }; |
| 88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
| 89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | interrupts = <35 1>; | 90 | interrupts = <5 1>; |
| 91 | reg = <1>; | 91 | reg = <1>; |
| 92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
| 93 | }; | 93 | }; |
| 94 | phy3: ethernet-phy@3 { | 94 | phy3: ethernet-phy@3 { |
| 95 | interrupt-parent = <&mpic>; | 95 | interrupt-parent = <&mpic>; |
| 96 | interrupts = <37 1>; | 96 | interrupts = <7 1>; |
| 97 | reg = <3>; | 97 | reg = <3>; |
| 98 | device_type = "ethernet-phy"; | 98 | device_type = "ethernet-phy"; |
| 99 | }; | 99 | }; |
| @@ -106,9 +106,14 @@ | |||
| 106 | model = "TSEC"; | 106 | model = "TSEC"; |
| 107 | compatible = "gianfar"; | 107 | compatible = "gianfar"; |
| 108 | reg = <24000 1000>; | 108 | reg = <24000 1000>; |
| 109 | address = [ 00 E0 0C 00 73 00 ]; | 109 | /* |
| 110 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 110 | * address is deprecated and will be removed |
| 111 | interrupts = <d 2 e 2 12 2>; | 111 | * in 2.6.25. Only recent versions of |
| 112 | * U-Boot support local-mac-address, however. | ||
| 113 | */ | ||
| 114 | address = [ 00 00 00 00 00 00 ]; | ||
| 115 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 116 | interrupts = <1d 2 1e 2 22 2>; | ||
| 112 | interrupt-parent = <&mpic>; | 117 | interrupt-parent = <&mpic>; |
| 113 | phy-handle = <&phy0>; | 118 | phy-handle = <&phy0>; |
| 114 | }; | 119 | }; |
| @@ -120,9 +125,14 @@ | |||
| 120 | model = "TSEC"; | 125 | model = "TSEC"; |
| 121 | compatible = "gianfar"; | 126 | compatible = "gianfar"; |
| 122 | reg = <25000 1000>; | 127 | reg = <25000 1000>; |
| 123 | address = [ 00 E0 0C 00 73 01 ]; | 128 | /* |
| 124 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 129 | * address is deprecated and will be removed |
| 125 | interrupts = <13 2 14 2 18 2>; | 130 | * in 2.6.25. Only recent versions of |
| 131 | * U-Boot support local-mac-address, however. | ||
| 132 | */ | ||
| 133 | address = [ 00 00 00 00 00 00 ]; | ||
| 134 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 135 | interrupts = <23 2 24 2 28 2>; | ||
| 126 | interrupt-parent = <&mpic>; | 136 | interrupt-parent = <&mpic>; |
| 127 | phy-handle = <&phy1>; | 137 | phy-handle = <&phy1>; |
| 128 | }; | 138 | }; |
| @@ -134,9 +144,14 @@ | |||
| 134 | model = "FEC"; | 144 | model = "FEC"; |
| 135 | compatible = "gianfar"; | 145 | compatible = "gianfar"; |
| 136 | reg = <26000 1000>; | 146 | reg = <26000 1000>; |
| 137 | address = [ 00 E0 0C 00 73 02 ]; | 147 | /* |
| 138 | local-mac-address = [ 00 E0 0C 00 73 02 ]; | 148 | * address is deprecated and will be removed |
| 139 | interrupts = <19 2>; | 149 | * in 2.6.25. Only recent versions of |
| 150 | * U-Boot support local-mac-address, however. | ||
| 151 | */ | ||
| 152 | address = [ 00 00 00 00 00 00 ]; | ||
| 153 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 154 | interrupts = <29 2>; | ||
| 140 | interrupt-parent = <&mpic>; | 155 | interrupt-parent = <&mpic>; |
| 141 | phy-handle = <&phy3>; | 156 | phy-handle = <&phy3>; |
| 142 | }; | 157 | }; |
| @@ -146,7 +161,7 @@ | |||
| 146 | compatible = "ns16550"; | 161 | compatible = "ns16550"; |
| 147 | reg = <4500 100>; // reg base, size | 162 | reg = <4500 100>; // reg base, size |
| 148 | clock-frequency = <0>; // should we fill in in uboot? | 163 | clock-frequency = <0>; // should we fill in in uboot? |
| 149 | interrupts = <1a 2>; | 164 | interrupts = <2a 2>; |
| 150 | interrupt-parent = <&mpic>; | 165 | interrupt-parent = <&mpic>; |
| 151 | }; | 166 | }; |
| 152 | 167 | ||
| @@ -155,7 +170,7 @@ | |||
| 155 | compatible = "ns16550"; | 170 | compatible = "ns16550"; |
| 156 | reg = <4600 100>; // reg base, size | 171 | reg = <4600 100>; // reg base, size |
| 157 | clock-frequency = <0>; // should we fill in in uboot? | 172 | clock-frequency = <0>; // should we fill in in uboot? |
| 158 | interrupts = <1a 2>; | 173 | interrupts = <2a 2>; |
| 159 | interrupt-parent = <&mpic>; | 174 | interrupt-parent = <&mpic>; |
| 160 | }; | 175 | }; |
| 161 | pci@8000 { | 176 | pci@8000 { |
| @@ -163,78 +178,78 @@ | |||
| 163 | interrupt-map = < | 178 | interrupt-map = < |
| 164 | 179 | ||
| 165 | /* IDSEL 0x02 */ | 180 | /* IDSEL 0x02 */ |
| 166 | 1000 0 0 1 &mpic 31 1 | 181 | 1000 0 0 1 &mpic 1 1 |
| 167 | 1000 0 0 2 &mpic 32 1 | 182 | 1000 0 0 2 &mpic 2 1 |
| 168 | 1000 0 0 3 &mpic 33 1 | 183 | 1000 0 0 3 &mpic 3 1 |
| 169 | 1000 0 0 4 &mpic 34 1 | 184 | 1000 0 0 4 &mpic 4 1 |
| 170 | 185 | ||
| 171 | /* IDSEL 0x03 */ | 186 | /* IDSEL 0x03 */ |
| 172 | 1800 0 0 1 &mpic 34 1 | 187 | 1800 0 0 1 &mpic 4 1 |
| 173 | 1800 0 0 2 &mpic 31 1 | 188 | 1800 0 0 2 &mpic 1 1 |
| 174 | 1800 0 0 3 &mpic 32 1 | 189 | 1800 0 0 3 &mpic 2 1 |
| 175 | 1800 0 0 4 &mpic 33 1 | 190 | 1800 0 0 4 &mpic 3 1 |
| 176 | 191 | ||
| 177 | /* IDSEL 0x04 */ | 192 | /* IDSEL 0x04 */ |
| 178 | 2000 0 0 1 &mpic 33 1 | 193 | 2000 0 0 1 &mpic 3 1 |
| 179 | 2000 0 0 2 &mpic 34 1 | 194 | 2000 0 0 2 &mpic 4 1 |
| 180 | 2000 0 0 3 &mpic 31 1 | 195 | 2000 0 0 3 &mpic 1 1 |
| 181 | 2000 0 0 4 &mpic 32 1 | 196 | 2000 0 0 4 &mpic 2 1 |
| 182 | 197 | ||
| 183 | /* IDSEL 0x05 */ | 198 | /* IDSEL 0x05 */ |
| 184 | 2800 0 0 1 &mpic 32 1 | 199 | 2800 0 0 1 &mpic 2 1 |
| 185 | 2800 0 0 2 &mpic 33 1 | 200 | 2800 0 0 2 &mpic 3 1 |
| 186 | 2800 0 0 3 &mpic 34 1 | 201 | 2800 0 0 3 &mpic 4 1 |
| 187 | 2800 0 0 4 &mpic 31 1 | 202 | 2800 0 0 4 &mpic 1 1 |
| 188 | 203 | ||
| 189 | /* IDSEL 0x0c */ | 204 | /* IDSEL 0x0c */ |
| 190 | 6000 0 0 1 &mpic 31 1 | 205 | 6000 0 0 1 &mpic 1 1 |
| 191 | 6000 0 0 2 &mpic 32 1 | 206 | 6000 0 0 2 &mpic 2 1 |
| 192 | 6000 0 0 3 &mpic 33 1 | 207 | 6000 0 0 3 &mpic 3 1 |
| 193 | 6000 0 0 4 &mpic 34 1 | 208 | 6000 0 0 4 &mpic 4 1 |
| 194 | 209 | ||
| 195 | /* IDSEL 0x0d */ | 210 | /* IDSEL 0x0d */ |
| 196 | 6800 0 0 1 &mpic 34 1 | 211 | 6800 0 0 1 &mpic 4 1 |
| 197 | 6800 0 0 2 &mpic 31 1 | 212 | 6800 0 0 2 &mpic 1 1 |
| 198 | 6800 0 0 3 &mpic 32 1 | 213 | 6800 0 0 3 &mpic 2 1 |
| 199 | 6800 0 0 4 &mpic 33 1 | 214 | 6800 0 0 4 &mpic 3 1 |
| 200 | 215 | ||
| 201 | /* IDSEL 0x0e */ | 216 | /* IDSEL 0x0e */ |
| 202 | 7000 0 0 1 &mpic 33 1 | 217 | 7000 0 0 1 &mpic 3 1 |
| 203 | 7000 0 0 2 &mpic 34 1 | 218 | 7000 0 0 2 &mpic 4 1 |
| 204 | 7000 0 0 3 &mpic 31 1 | 219 | 7000 0 0 3 &mpic 1 1 |
| 205 | 7000 0 0 4 &mpic 32 1 | 220 | 7000 0 0 4 &mpic 2 1 |
| 206 | 221 | ||
| 207 | /* IDSEL 0x0f */ | 222 | /* IDSEL 0x0f */ |
| 208 | 7800 0 0 1 &mpic 32 1 | 223 | 7800 0 0 1 &mpic 2 1 |
| 209 | 7800 0 0 2 &mpic 33 1 | 224 | 7800 0 0 2 &mpic 3 1 |
| 210 | 7800 0 0 3 &mpic 34 1 | 225 | 7800 0 0 3 &mpic 4 1 |
| 211 | 7800 0 0 4 &mpic 31 1 | 226 | 7800 0 0 4 &mpic 1 1 |
| 212 | 227 | ||
| 213 | /* IDSEL 0x12 */ | 228 | /* IDSEL 0x12 */ |
| 214 | 9000 0 0 1 &mpic 31 1 | 229 | 9000 0 0 1 &mpic 1 1 |
| 215 | 9000 0 0 2 &mpic 32 1 | 230 | 9000 0 0 2 &mpic 2 1 |
| 216 | 9000 0 0 3 &mpic 33 1 | 231 | 9000 0 0 3 &mpic 3 1 |
| 217 | 9000 0 0 4 &mpic 34 1 | 232 | 9000 0 0 4 &mpic 4 1 |
| 218 | 233 | ||
| 219 | /* IDSEL 0x13 */ | 234 | /* IDSEL 0x13 */ |
| 220 | 9800 0 0 1 &mpic 34 1 | 235 | 9800 0 0 1 &mpic 4 1 |
| 221 | 9800 0 0 2 &mpic 31 1 | 236 | 9800 0 0 2 &mpic 1 1 |
| 222 | 9800 0 0 3 &mpic 32 1 | 237 | 9800 0 0 3 &mpic 2 1 |
| 223 | 9800 0 0 4 &mpic 33 1 | 238 | 9800 0 0 4 &mpic 3 1 |
| 224 | 239 | ||
| 225 | /* IDSEL 0x14 */ | 240 | /* IDSEL 0x14 */ |
| 226 | a000 0 0 1 &mpic 33 1 | 241 | a000 0 0 1 &mpic 3 1 |
| 227 | a000 0 0 2 &mpic 34 1 | 242 | a000 0 0 2 &mpic 4 1 |
| 228 | a000 0 0 3 &mpic 31 1 | 243 | a000 0 0 3 &mpic 1 1 |
| 229 | a000 0 0 4 &mpic 32 1 | 244 | a000 0 0 4 &mpic 2 1 |
| 230 | 245 | ||
| 231 | /* IDSEL 0x15 */ | 246 | /* IDSEL 0x15 */ |
| 232 | a800 0 0 1 &mpic 32 1 | 247 | a800 0 0 1 &mpic 2 1 |
| 233 | a800 0 0 2 &mpic 33 1 | 248 | a800 0 0 2 &mpic 3 1 |
| 234 | a800 0 0 3 &mpic 34 1 | 249 | a800 0 0 3 &mpic 4 1 |
| 235 | a800 0 0 4 &mpic 31 1>; | 250 | a800 0 0 4 &mpic 1 1>; |
| 236 | interrupt-parent = <&mpic>; | 251 | interrupt-parent = <&mpic>; |
| 237 | interrupts = <08 2>; | 252 | interrupts = <18 2>; |
| 238 | bus-range = <0 0>; | 253 | bus-range = <0 0>; |
| 239 | ranges = <02000000 0 80000000 80000000 0 20000000 | 254 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 240 | 01000000 0 00000000 e2000000 0 00100000>; | 255 | 01000000 0 00000000 e2000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts index 4f2c3af2e052..070206fffe88 100644 --- a/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/arch/powerpc/boot/dts/mpc8541cds.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8541-memory-controller"; | 52 | compatible = "fsl,8541-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,14 +61,14 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | i2c@3000 { | 67 | i2c@3000 { |
| 68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
| 69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
| 70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
| 71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | dfsrr; | 73 | dfsrr; |
| 74 | }; | 74 | }; |
| @@ -81,13 +81,13 @@ | |||
| 81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
| 82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
| 83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
| 84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
| 85 | reg = <0>; | 85 | reg = <0>; |
| 86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
| 87 | }; | 87 | }; |
| 88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
| 89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
| 91 | reg = <1>; | 91 | reg = <1>; |
| 92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
| 93 | }; | 93 | }; |
| @@ -100,8 +100,8 @@ | |||
| 100 | model = "TSEC"; | 100 | model = "TSEC"; |
| 101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
| 102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
| 103 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 104 | interrupts = <d 2 e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
| 105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
| 106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
| 107 | }; | 107 | }; |
| @@ -113,8 +113,8 @@ | |||
| 113 | model = "TSEC"; | 113 | model = "TSEC"; |
| 114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
| 115 | reg = <25000 1000>; | 115 | reg = <25000 1000>; |
| 116 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 117 | interrupts = <13 2 14 2 18 2>; | 117 | interrupts = <23 2 24 2 28 2>; |
| 118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
| 119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
| 120 | }; | 120 | }; |
| @@ -124,7 +124,7 @@ | |||
| 124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
| 125 | reg = <4500 100>; // reg base, size | 125 | reg = <4500 100>; // reg base, size |
| 126 | clock-frequency = <0>; // should we fill in in uboot? | 126 | clock-frequency = <0>; // should we fill in in uboot? |
| 127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
| 128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| @@ -133,7 +133,7 @@ | |||
| 133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
| 134 | reg = <4600 100>; // reg base, size | 134 | reg = <4600 100>; // reg base, size |
| 135 | clock-frequency = <0>; // should we fill in in uboot? | 135 | clock-frequency = <0>; // should we fill in in uboot? |
| 136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
| 137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
| @@ -142,49 +142,49 @@ | |||
| 142 | interrupt-map = < | 142 | interrupt-map = < |
| 143 | 143 | ||
| 144 | /* IDSEL 0x10 */ | 144 | /* IDSEL 0x10 */ |
| 145 | 08000 0 0 1 &mpic 30 1 | 145 | 08000 0 0 1 &mpic 0 1 |
| 146 | 08000 0 0 2 &mpic 31 1 | 146 | 08000 0 0 2 &mpic 1 1 |
| 147 | 08000 0 0 3 &mpic 32 1 | 147 | 08000 0 0 3 &mpic 2 1 |
| 148 | 08000 0 0 4 &mpic 33 1 | 148 | 08000 0 0 4 &mpic 3 1 |
| 149 | 149 | ||
| 150 | /* IDSEL 0x11 */ | 150 | /* IDSEL 0x11 */ |
| 151 | 08800 0 0 1 &mpic 30 1 | 151 | 08800 0 0 1 &mpic 0 1 |
| 152 | 08800 0 0 2 &mpic 31 1 | 152 | 08800 0 0 2 &mpic 1 1 |
| 153 | 08800 0 0 3 &mpic 32 1 | 153 | 08800 0 0 3 &mpic 2 1 |
| 154 | 08800 0 0 4 &mpic 33 1 | 154 | 08800 0 0 4 &mpic 3 1 |
| 155 | 155 | ||
| 156 | /* IDSEL 0x12 (Slot 1) */ | 156 | /* IDSEL 0x12 (Slot 1) */ |
| 157 | 09000 0 0 1 &mpic 30 1 | 157 | 09000 0 0 1 &mpic 0 1 |
| 158 | 09000 0 0 2 &mpic 31 1 | 158 | 09000 0 0 2 &mpic 1 1 |
| 159 | 09000 0 0 3 &mpic 32 1 | 159 | 09000 0 0 3 &mpic 2 1 |
| 160 | 09000 0 0 4 &mpic 33 1 | 160 | 09000 0 0 4 &mpic 3 1 |
| 161 | 161 | ||
| 162 | /* IDSEL 0x13 (Slot 2) */ | 162 | /* IDSEL 0x13 (Slot 2) */ |
| 163 | 09800 0 0 1 &mpic 31 1 | 163 | 09800 0 0 1 &mpic 1 1 |
| 164 | 09800 0 0 2 &mpic 32 1 | 164 | 09800 0 0 2 &mpic 2 1 |
| 165 | 09800 0 0 3 &mpic 33 1 | 165 | 09800 0 0 3 &mpic 3 1 |
| 166 | 09800 0 0 4 &mpic 30 1 | 166 | 09800 0 0 4 &mpic 0 1 |
| 167 | 167 | ||
| 168 | /* IDSEL 0x14 (Slot 3) */ | 168 | /* IDSEL 0x14 (Slot 3) */ |
| 169 | 0a000 0 0 1 &mpic 32 1 | 169 | 0a000 0 0 1 &mpic 2 1 |
| 170 | 0a000 0 0 2 &mpic 33 1 | 170 | 0a000 0 0 2 &mpic 3 1 |
| 171 | 0a000 0 0 3 &mpic 30 1 | 171 | 0a000 0 0 3 &mpic 0 1 |
| 172 | 0a000 0 0 4 &mpic 31 1 | 172 | 0a000 0 0 4 &mpic 1 1 |
| 173 | 173 | ||
| 174 | /* IDSEL 0x15 (Slot 4) */ | 174 | /* IDSEL 0x15 (Slot 4) */ |
| 175 | 0a800 0 0 1 &mpic 33 1 | 175 | 0a800 0 0 1 &mpic 3 1 |
| 176 | 0a800 0 0 2 &mpic 30 1 | 176 | 0a800 0 0 2 &mpic 0 1 |
| 177 | 0a800 0 0 3 &mpic 31 1 | 177 | 0a800 0 0 3 &mpic 1 1 |
| 178 | 0a800 0 0 4 &mpic 32 1 | 178 | 0a800 0 0 4 &mpic 2 1 |
| 179 | 179 | ||
| 180 | /* Bus 1 (Tundra Bridge) */ | 180 | /* Bus 1 (Tundra Bridge) */ |
| 181 | /* IDSEL 0x12 (ISA bridge) */ | 181 | /* IDSEL 0x12 (ISA bridge) */ |
| 182 | 19000 0 0 1 &mpic 30 1 | 182 | 19000 0 0 1 &mpic 0 1 |
| 183 | 19000 0 0 2 &mpic 31 1 | 183 | 19000 0 0 2 &mpic 1 1 |
| 184 | 19000 0 0 3 &mpic 32 1 | 184 | 19000 0 0 3 &mpic 2 1 |
| 185 | 19000 0 0 4 &mpic 33 1>; | 185 | 19000 0 0 4 &mpic 3 1>; |
| 186 | interrupt-parent = <&mpic>; | 186 | interrupt-parent = <&mpic>; |
| 187 | interrupts = <08 2>; | 187 | interrupts = <18 2>; |
| 188 | bus-range = <0 0>; | 188 | bus-range = <0 0>; |
| 189 | ranges = <02000000 0 80000000 80000000 0 20000000 | 189 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 190 | 01000000 0 00000000 e2000000 0 00100000>; | 190 | 01000000 0 00000000 e2000000 0 00100000>; |
| @@ -216,12 +216,12 @@ | |||
| 216 | interrupt-map = < | 216 | interrupt-map = < |
| 217 | 217 | ||
| 218 | /* IDSEL 0x15 */ | 218 | /* IDSEL 0x15 */ |
| 219 | a800 0 0 1 &mpic 3b 1 | 219 | a800 0 0 1 &mpic b 1 |
| 220 | a800 0 0 2 &mpic 3b 1 | 220 | a800 0 0 2 &mpic b 1 |
| 221 | a800 0 0 3 &mpic 3b 1 | 221 | a800 0 0 3 &mpic b 1 |
| 222 | a800 0 0 4 &mpic 3b 1>; | 222 | a800 0 0 4 &mpic b 1>; |
| 223 | interrupt-parent = <&mpic>; | 223 | interrupt-parent = <&mpic>; |
| 224 | interrupts = <09 2>; | 224 | interrupts = <19 2>; |
| 225 | bus-range = <0 0>; | 225 | bus-range = <0 0>; |
| 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
| 227 | 01000000 0 00000000 e3000000 0 00100000>; | 227 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts index 3033599e74e8..828592592460 100644 --- a/arch/powerpc/boot/dts/mpc8544ds.dts +++ b/arch/powerpc/boot/dts/mpc8544ds.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8544-memory-controller"; | 52 | compatible = "fsl,8544-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,14 +61,14 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | i2c@3000 { | 67 | i2c@3000 { |
| 68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
| 69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
| 70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
| 71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | dfsrr; | 73 | dfsrr; |
| 74 | }; | 74 | }; |
| @@ -81,13 +81,13 @@ | |||
| 81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
| 82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
| 83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
| 84 | interrupts = <3a 1>; | 84 | interrupts = <a 1>; |
| 85 | reg = <0>; | 85 | reg = <0>; |
| 86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
| 87 | }; | 87 | }; |
| 88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
| 89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | interrupts = <3a 1>; | 90 | interrupts = <a 1>; |
| 91 | reg = <1>; | 91 | reg = <1>; |
| 92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
| 93 | }; | 93 | }; |
| @@ -101,7 +101,7 @@ | |||
| 101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
| 102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
| 103 | local-mac-address = [ 00 00 00 00 00 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 104 | interrupts = <d 2 e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
| 105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
| 106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
| 107 | }; | 107 | }; |
| @@ -114,7 +114,7 @@ | |||
| 114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
| 115 | reg = <26000 1000>; | 115 | reg = <26000 1000>; |
| 116 | local-mac-address = [ 00 00 00 00 00 00 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 117 | interrupts = <f 2 10 2 11 2>; | 117 | interrupts = <1f 2 20 2 21 2>; |
| 118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
| 119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
| 120 | }; | 120 | }; |
| @@ -124,7 +124,7 @@ | |||
| 124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
| 125 | reg = <4500 100>; | 125 | reg = <4500 100>; |
| 126 | clock-frequency = <0>; | 126 | clock-frequency = <0>; |
| 127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
| 128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| @@ -133,7 +133,7 @@ | |||
| 133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
| 134 | reg = <4600 100>; | 134 | reg = <4600 100>; |
| 135 | clock-frequency = <0>; | 135 | clock-frequency = <0>; |
| 136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
| 137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index ad96381033c0..9d0b84b66cd4 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8548-memory-controller"; | 52 | compatible = "fsl,8548-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,14 +61,14 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <80000>; // L2, 512K | 62 | cache-size = <80000>; // L2, 512K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | i2c@3000 { | 67 | i2c@3000 { |
| 68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
| 69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
| 70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
| 71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | dfsrr; | 73 | dfsrr; |
| 74 | }; | 74 | }; |
| @@ -81,25 +81,25 @@ | |||
| 81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
| 82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
| 83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
| 84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
| 85 | reg = <0>; | 85 | reg = <0>; |
| 86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
| 87 | }; | 87 | }; |
| 88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
| 89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
| 91 | reg = <1>; | 91 | reg = <1>; |
| 92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
| 93 | }; | 93 | }; |
| 94 | phy2: ethernet-phy@2 { | 94 | phy2: ethernet-phy@2 { |
| 95 | interrupt-parent = <&mpic>; | 95 | interrupt-parent = <&mpic>; |
| 96 | interrupts = <35 0>; | 96 | interrupts = <5 1>; |
| 97 | reg = <2>; | 97 | reg = <2>; |
| 98 | device_type = "ethernet-phy"; | 98 | device_type = "ethernet-phy"; |
| 99 | }; | 99 | }; |
| 100 | phy3: ethernet-phy@3 { | 100 | phy3: ethernet-phy@3 { |
| 101 | interrupt-parent = <&mpic>; | 101 | interrupt-parent = <&mpic>; |
| 102 | interrupts = <35 0>; | 102 | interrupts = <5 1>; |
| 103 | reg = <3>; | 103 | reg = <3>; |
| 104 | device_type = "ethernet-phy"; | 104 | device_type = "ethernet-phy"; |
| 105 | }; | 105 | }; |
| @@ -112,8 +112,8 @@ | |||
| 112 | model = "eTSEC"; | 112 | model = "eTSEC"; |
| 113 | compatible = "gianfar"; | 113 | compatible = "gianfar"; |
| 114 | reg = <24000 1000>; | 114 | reg = <24000 1000>; |
| 115 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 115 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 116 | interrupts = <d 2 e 2 12 2>; | 116 | interrupts = <1d 2 1e 2 22 2>; |
| 117 | interrupt-parent = <&mpic>; | 117 | interrupt-parent = <&mpic>; |
| 118 | phy-handle = <&phy0>; | 118 | phy-handle = <&phy0>; |
| 119 | }; | 119 | }; |
| @@ -125,8 +125,8 @@ | |||
| 125 | model = "eTSEC"; | 125 | model = "eTSEC"; |
| 126 | compatible = "gianfar"; | 126 | compatible = "gianfar"; |
| 127 | reg = <25000 1000>; | 127 | reg = <25000 1000>; |
| 128 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 128 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 129 | interrupts = <13 2 14 2 18 2>; | 129 | interrupts = <23 2 24 2 28 2>; |
| 130 | interrupt-parent = <&mpic>; | 130 | interrupt-parent = <&mpic>; |
| 131 | phy-handle = <&phy1>; | 131 | phy-handle = <&phy1>; |
| 132 | }; | 132 | }; |
| @@ -139,8 +139,8 @@ | |||
| 139 | model = "eTSEC"; | 139 | model = "eTSEC"; |
| 140 | compatible = "gianfar"; | 140 | compatible = "gianfar"; |
| 141 | reg = <26000 1000>; | 141 | reg = <26000 1000>; |
| 142 | local-mac-address = [ 00 E0 0C 00 73 02 ]; | 142 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 143 | interrupts = <f 2 10 2 11 2>; | 143 | interrupts = <1f 2 20 2 21 2>; |
| 144 | interrupt-parent = <&mpic>; | 144 | interrupt-parent = <&mpic>; |
| 145 | phy-handle = <&phy2>; | 145 | phy-handle = <&phy2>; |
| 146 | }; | 146 | }; |
| @@ -152,8 +152,8 @@ | |||
| 152 | model = "eTSEC"; | 152 | model = "eTSEC"; |
| 153 | compatible = "gianfar"; | 153 | compatible = "gianfar"; |
| 154 | reg = <27000 1000>; | 154 | reg = <27000 1000>; |
| 155 | local-mac-address = [ 00 E0 0C 00 73 03 ]; | 155 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 156 | interrupts = <15 2 16 2 17 2>; | 156 | interrupts = <25 2 26 2 27 2>; |
| 157 | interrupt-parent = <&mpic>; | 157 | interrupt-parent = <&mpic>; |
| 158 | phy-handle = <&phy3>; | 158 | phy-handle = <&phy3>; |
| 159 | }; | 159 | }; |
| @@ -164,7 +164,7 @@ | |||
| 164 | compatible = "ns16550"; | 164 | compatible = "ns16550"; |
| 165 | reg = <4500 100>; // reg base, size | 165 | reg = <4500 100>; // reg base, size |
| 166 | clock-frequency = <0>; // should we fill in in uboot? | 166 | clock-frequency = <0>; // should we fill in in uboot? |
| 167 | interrupts = <1a 2>; | 167 | interrupts = <2a 2>; |
| 168 | interrupt-parent = <&mpic>; | 168 | interrupt-parent = <&mpic>; |
| 169 | }; | 169 | }; |
| 170 | 170 | ||
| @@ -173,58 +173,64 @@ | |||
| 173 | compatible = "ns16550"; | 173 | compatible = "ns16550"; |
| 174 | reg = <4600 100>; // reg base, size | 174 | reg = <4600 100>; // reg base, size |
| 175 | clock-frequency = <0>; // should we fill in in uboot? | 175 | clock-frequency = <0>; // should we fill in in uboot? |
| 176 | interrupts = <1a 2>; | 176 | interrupts = <2a 2>; |
| 177 | interrupt-parent = <&mpic>; | 177 | interrupt-parent = <&mpic>; |
| 178 | }; | 178 | }; |
| 179 | 179 | ||
| 180 | global-utilities@e0000 { //global utilities reg | ||
| 181 | compatible = "fsl,mpc8548-guts"; | ||
| 182 | reg = <e0000 1000>; | ||
| 183 | fsl,has-rstcr; | ||
| 184 | }; | ||
| 185 | |||
| 180 | pci1: pci@8000 { | 186 | pci1: pci@8000 { |
| 181 | interrupt-map-mask = <1f800 0 0 7>; | 187 | interrupt-map-mask = <1f800 0 0 7>; |
| 182 | interrupt-map = < | 188 | interrupt-map = < |
| 183 | 189 | ||
| 184 | /* IDSEL 0x10 */ | 190 | /* IDSEL 0x10 */ |
| 185 | 08000 0 0 1 &mpic 30 1 | 191 | 08000 0 0 1 &mpic 0 1 |
| 186 | 08000 0 0 2 &mpic 31 1 | 192 | 08000 0 0 2 &mpic 1 1 |
| 187 | 08000 0 0 3 &mpic 32 1 | 193 | 08000 0 0 3 &mpic 2 1 |
| 188 | 08000 0 0 4 &mpic 33 1 | 194 | 08000 0 0 4 &mpic 3 1 |
| 189 | 195 | ||
| 190 | /* IDSEL 0x11 */ | 196 | /* IDSEL 0x11 */ |
| 191 | 08800 0 0 1 &mpic 30 1 | 197 | 08800 0 0 1 &mpic 0 1 |
| 192 | 08800 0 0 2 &mpic 31 1 | 198 | 08800 0 0 2 &mpic 1 1 |
| 193 | 08800 0 0 3 &mpic 32 1 | 199 | 08800 0 0 3 &mpic 2 1 |
| 194 | 08800 0 0 4 &mpic 33 1 | 200 | 08800 0 0 4 &mpic 3 1 |
| 195 | 201 | ||
| 196 | /* IDSEL 0x12 (Slot 1) */ | 202 | /* IDSEL 0x12 (Slot 1) */ |
| 197 | 09000 0 0 1 &mpic 30 1 | 203 | 09000 0 0 1 &mpic 0 1 |
| 198 | 09000 0 0 2 &mpic 31 1 | 204 | 09000 0 0 2 &mpic 1 1 |
| 199 | 09000 0 0 3 &mpic 32 1 | 205 | 09000 0 0 3 &mpic 2 1 |
| 200 | 09000 0 0 4 &mpic 33 1 | 206 | 09000 0 0 4 &mpic 3 1 |
| 201 | 207 | ||
| 202 | /* IDSEL 0x13 (Slot 2) */ | 208 | /* IDSEL 0x13 (Slot 2) */ |
| 203 | 09800 0 0 1 &mpic 31 1 | 209 | 09800 0 0 1 &mpic 1 1 |
| 204 | 09800 0 0 2 &mpic 32 1 | 210 | 09800 0 0 2 &mpic 2 1 |
| 205 | 09800 0 0 3 &mpic 33 1 | 211 | 09800 0 0 3 &mpic 3 1 |
| 206 | 09800 0 0 4 &mpic 30 1 | 212 | 09800 0 0 4 &mpic 0 1 |
| 207 | 213 | ||
| 208 | /* IDSEL 0x14 (Slot 3) */ | 214 | /* IDSEL 0x14 (Slot 3) */ |
| 209 | 0a000 0 0 1 &mpic 32 1 | 215 | 0a000 0 0 1 &mpic 2 1 |
| 210 | 0a000 0 0 2 &mpic 33 1 | 216 | 0a000 0 0 2 &mpic 3 1 |
| 211 | 0a000 0 0 3 &mpic 30 1 | 217 | 0a000 0 0 3 &mpic 0 1 |
| 212 | 0a000 0 0 4 &mpic 31 1 | 218 | 0a000 0 0 4 &mpic 1 1 |
| 213 | 219 | ||
| 214 | /* IDSEL 0x15 (Slot 4) */ | 220 | /* IDSEL 0x15 (Slot 4) */ |
| 215 | 0a800 0 0 1 &mpic 33 1 | 221 | 0a800 0 0 1 &mpic 3 1 |
| 216 | 0a800 0 0 2 &mpic 30 1 | 222 | 0a800 0 0 2 &mpic 0 1 |
| 217 | 0a800 0 0 3 &mpic 31 1 | 223 | 0a800 0 0 3 &mpic 1 1 |
| 218 | 0a800 0 0 4 &mpic 32 1 | 224 | 0a800 0 0 4 &mpic 2 1 |
| 219 | 225 | ||
| 220 | /* Bus 1 (Tundra Bridge) */ | 226 | /* Bus 1 (Tundra Bridge) */ |
| 221 | /* IDSEL 0x12 (ISA bridge) */ | 227 | /* IDSEL 0x12 (ISA bridge) */ |
| 222 | 19000 0 0 1 &mpic 30 1 | 228 | 19000 0 0 1 &mpic 0 1 |
| 223 | 19000 0 0 2 &mpic 31 1 | 229 | 19000 0 0 2 &mpic 1 1 |
| 224 | 19000 0 0 3 &mpic 32 1 | 230 | 19000 0 0 3 &mpic 2 1 |
| 225 | 19000 0 0 4 &mpic 33 1>; | 231 | 19000 0 0 4 &mpic 3 1>; |
| 226 | interrupt-parent = <&mpic>; | 232 | interrupt-parent = <&mpic>; |
| 227 | interrupts = <08 2>; | 233 | interrupts = <18 2>; |
| 228 | bus-range = <0 0>; | 234 | bus-range = <0 0>; |
| 229 | ranges = <02000000 0 80000000 80000000 0 20000000 | 235 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 230 | 01000000 0 00000000 e2000000 0 00100000>; | 236 | 01000000 0 00000000 e2000000 0 00100000>; |
| @@ -256,12 +262,12 @@ | |||
| 256 | interrupt-map = < | 262 | interrupt-map = < |
| 257 | 263 | ||
| 258 | /* IDSEL 0x15 */ | 264 | /* IDSEL 0x15 */ |
| 259 | a800 0 0 1 &mpic 3b 1 | 265 | a800 0 0 1 &mpic b 1 |
| 260 | a800 0 0 2 &mpic 3b 1 | 266 | a800 0 0 2 &mpic b 1 |
| 261 | a800 0 0 3 &mpic 3b 1 | 267 | a800 0 0 3 &mpic b 1 |
| 262 | a800 0 0 4 &mpic 3b 1>; | 268 | a800 0 0 4 &mpic b 1>; |
| 263 | interrupt-parent = <&mpic>; | 269 | interrupt-parent = <&mpic>; |
| 264 | interrupts = <09 2>; | 270 | interrupts = <19 2>; |
| 265 | bus-range = <0 0>; | 271 | bus-range = <0 0>; |
| 266 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 272 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
| 267 | 01000000 0 00000000 e3000000 0 00100000>; | 273 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts index 951ed92f1154..17e45d9a382a 100644 --- a/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/arch/powerpc/boot/dts/mpc8555cds.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8555-memory-controller"; | 52 | compatible = "fsl,8555-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,14 +61,14 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | i2c@3000 { | 67 | i2c@3000 { |
| 68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
| 69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
| 70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
| 71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | dfsrr; | 73 | dfsrr; |
| 74 | }; | 74 | }; |
| @@ -81,13 +81,13 @@ | |||
| 81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
| 82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
| 83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
| 84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
| 85 | reg = <0>; | 85 | reg = <0>; |
| 86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
| 87 | }; | 87 | }; |
| 88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
| 89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
| 90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
| 91 | reg = <1>; | 91 | reg = <1>; |
| 92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
| 93 | }; | 93 | }; |
| @@ -100,8 +100,8 @@ | |||
| 100 | model = "TSEC"; | 100 | model = "TSEC"; |
| 101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
| 102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
| 103 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 104 | interrupts = <0d 2 0e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
| 105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
| 106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
| 107 | }; | 107 | }; |
| @@ -113,8 +113,8 @@ | |||
| 113 | model = "TSEC"; | 113 | model = "TSEC"; |
| 114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
| 115 | reg = <25000 1000>; | 115 | reg = <25000 1000>; |
| 116 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 117 | interrupts = <13 2 14 2 18 2>; | 117 | interrupts = <23 2 24 2 28 2>; |
| 118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
| 119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
| 120 | }; | 120 | }; |
| @@ -124,7 +124,7 @@ | |||
| 124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
| 125 | reg = <4500 100>; // reg base, size | 125 | reg = <4500 100>; // reg base, size |
| 126 | clock-frequency = <0>; // should we fill in in uboot? | 126 | clock-frequency = <0>; // should we fill in in uboot? |
| 127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
| 128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| @@ -133,7 +133,7 @@ | |||
| 133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
| 134 | reg = <4600 100>; // reg base, size | 134 | reg = <4600 100>; // reg base, size |
| 135 | clock-frequency = <0>; // should we fill in in uboot? | 135 | clock-frequency = <0>; // should we fill in in uboot? |
| 136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
| 137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
| @@ -142,49 +142,49 @@ | |||
| 142 | interrupt-map = < | 142 | interrupt-map = < |
| 143 | 143 | ||
| 144 | /* IDSEL 0x10 */ | 144 | /* IDSEL 0x10 */ |
| 145 | 08000 0 0 1 &mpic 30 1 | 145 | 08000 0 0 1 &mpic 0 1 |
| 146 | 08000 0 0 2 &mpic 31 1 | 146 | 08000 0 0 2 &mpic 1 1 |
| 147 | 08000 0 0 3 &mpic 32 1 | 147 | 08000 0 0 3 &mpic 2 1 |
| 148 | 08000 0 0 4 &mpic 33 1 | 148 | 08000 0 0 4 &mpic 3 1 |
| 149 | 149 | ||
| 150 | /* IDSEL 0x11 */ | 150 | /* IDSEL 0x11 */ |
| 151 | 08800 0 0 1 &mpic 30 1 | 151 | 08800 0 0 1 &mpic 0 1 |
| 152 | 08800 0 0 2 &mpic 31 1 | 152 | 08800 0 0 2 &mpic 1 1 |
| 153 | 08800 0 0 3 &mpic 32 1 | 153 | 08800 0 0 3 &mpic 2 1 |
| 154 | 08800 0 0 4 &mpic 33 1 | 154 | 08800 0 0 4 &mpic 3 1 |
| 155 | 155 | ||
| 156 | /* IDSEL 0x12 (Slot 1) */ | 156 | /* IDSEL 0x12 (Slot 1) */ |
| 157 | 09000 0 0 1 &mpic 30 1 | 157 | 09000 0 0 1 &mpic 0 1 |
| 158 | 09000 0 0 2 &mpic 31 1 | 158 | 09000 0 0 2 &mpic 1 1 |
| 159 | 09000 0 0 3 &mpic 32 1 | 159 | 09000 0 0 3 &mpic 2 1 |
| 160 | 09000 0 0 4 &mpic 33 1 | 160 | 09000 0 0 4 &mpic 3 1 |
| 161 | 161 | ||
| 162 | /* IDSEL 0x13 (Slot 2) */ | 162 | /* IDSEL 0x13 (Slot 2) */ |
| 163 | 09800 0 0 1 &mpic 31 1 | 163 | 09800 0 0 1 &mpic 1 1 |
| 164 | 09800 0 0 2 &mpic 32 1 | 164 | 09800 0 0 2 &mpic 2 1 |
| 165 | 09800 0 0 3 &mpic 33 1 | 165 | 09800 0 0 3 &mpic 3 1 |
| 166 | 09800 0 0 4 &mpic 30 1 | 166 | 09800 0 0 4 &mpic 0 1 |
| 167 | 167 | ||
| 168 | /* IDSEL 0x14 (Slot 3) */ | 168 | /* IDSEL 0x14 (Slot 3) */ |
| 169 | 0a000 0 0 1 &mpic 32 1 | 169 | 0a000 0 0 1 &mpic 2 1 |
| 170 | 0a000 0 0 2 &mpic 33 1 | 170 | 0a000 0 0 2 &mpic 3 1 |
| 171 | 0a000 0 0 3 &mpic 30 1 | 171 | 0a000 0 0 3 &mpic 0 1 |
| 172 | 0a000 0 0 4 &mpic 31 1 | 172 | 0a000 0 0 4 &mpic 1 1 |
| 173 | 173 | ||
| 174 | /* IDSEL 0x15 (Slot 4) */ | 174 | /* IDSEL 0x15 (Slot 4) */ |
| 175 | 0a800 0 0 1 &mpic 33 1 | 175 | 0a800 0 0 1 &mpic 3 1 |
| 176 | 0a800 0 0 2 &mpic 30 1 | 176 | 0a800 0 0 2 &mpic 0 1 |
| 177 | 0a800 0 0 3 &mpic 31 1 | 177 | 0a800 0 0 3 &mpic 1 1 |
| 178 | 0a800 0 0 4 &mpic 32 1 | 178 | 0a800 0 0 4 &mpic 2 1 |
| 179 | 179 | ||
| 180 | /* Bus 1 (Tundra Bridge) */ | 180 | /* Bus 1 (Tundra Bridge) */ |
| 181 | /* IDSEL 0x12 (ISA bridge) */ | 181 | /* IDSEL 0x12 (ISA bridge) */ |
| 182 | 19000 0 0 1 &mpic 30 1 | 182 | 19000 0 0 1 &mpic 0 1 |
| 183 | 19000 0 0 2 &mpic 31 1 | 183 | 19000 0 0 2 &mpic 1 1 |
| 184 | 19000 0 0 3 &mpic 32 1 | 184 | 19000 0 0 3 &mpic 2 1 |
| 185 | 19000 0 0 4 &mpic 33 1>; | 185 | 19000 0 0 4 &mpic 3 1>; |
| 186 | interrupt-parent = <&mpic>; | 186 | interrupt-parent = <&mpic>; |
| 187 | interrupts = <08 2>; | 187 | interrupts = <18 2>; |
| 188 | bus-range = <0 0>; | 188 | bus-range = <0 0>; |
| 189 | ranges = <02000000 0 80000000 80000000 0 20000000 | 189 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 190 | 01000000 0 00000000 e2000000 0 00100000>; | 190 | 01000000 0 00000000 e2000000 0 00100000>; |
| @@ -216,12 +216,12 @@ | |||
| 216 | interrupt-map = < | 216 | interrupt-map = < |
| 217 | 217 | ||
| 218 | /* IDSEL 0x15 */ | 218 | /* IDSEL 0x15 */ |
| 219 | a800 0 0 1 &mpic 3b 1 | 219 | a800 0 0 1 &mpic b 1 |
| 220 | a800 0 0 2 &mpic 3b 1 | 220 | a800 0 0 2 &mpic b 1 |
| 221 | a800 0 0 3 &mpic 3b 1 | 221 | a800 0 0 3 &mpic b 1 |
| 222 | a800 0 0 4 &mpic 3b 1>; | 222 | a800 0 0 4 &mpic b 1>; |
| 223 | interrupt-parent = <&mpic>; | 223 | interrupt-parent = <&mpic>; |
| 224 | interrupts = <09 2>; | 224 | interrupts = <19 2>; |
| 225 | bus-range = <0 0>; | 225 | bus-range = <0 0>; |
| 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
| 227 | 01000000 0 00000000 e3000000 0 00100000>; | 227 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts index 80682152b0cf..21ccaaa27993 100644 --- a/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/arch/powerpc/boot/dts/mpc8560ads.dts | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | compatible = "fsl,8540-memory-controller"; | 52 | compatible = "fsl,8540-memory-controller"; |
| 53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
| 54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
| 55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
| @@ -61,7 +61,7 @@ | |||
| 61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
| 62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | mdio@24520 { | 67 | mdio@24520 { |
| @@ -72,25 +72,25 @@ | |||
| 72 | #size-cells = <0>; | 72 | #size-cells = <0>; |
| 73 | phy0: ethernet-phy@0 { | 73 | phy0: ethernet-phy@0 { |
| 74 | interrupt-parent = <&mpic>; | 74 | interrupt-parent = <&mpic>; |
| 75 | interrupts = <35 1>; | 75 | interrupts = <5 1>; |
| 76 | reg = <0>; | 76 | reg = <0>; |
| 77 | device_type = "ethernet-phy"; | 77 | device_type = "ethernet-phy"; |
| 78 | }; | 78 | }; |
| 79 | phy1: ethernet-phy@1 { | 79 | phy1: ethernet-phy@1 { |
| 80 | interrupt-parent = <&mpic>; | 80 | interrupt-parent = <&mpic>; |
| 81 | interrupts = <35 1>; | 81 | interrupts = <5 1>; |
| 82 | reg = <1>; | 82 | reg = <1>; |
| 83 | device_type = "ethernet-phy"; | 83 | device_type = "ethernet-phy"; |
| 84 | }; | 84 | }; |
| 85 | phy2: ethernet-phy@2 { | 85 | phy2: ethernet-phy@2 { |
| 86 | interrupt-parent = <&mpic>; | 86 | interrupt-parent = <&mpic>; |
| 87 | interrupts = <37 1>; | 87 | interrupts = <7 1>; |
| 88 | reg = <2>; | 88 | reg = <2>; |
| 89 | device_type = "ethernet-phy"; | 89 | device_type = "ethernet-phy"; |
| 90 | }; | 90 | }; |
| 91 | phy3: ethernet-phy@3 { | 91 | phy3: ethernet-phy@3 { |
| 92 | interrupt-parent = <&mpic>; | 92 | interrupt-parent = <&mpic>; |
| 93 | interrupts = <37 1>; | 93 | interrupts = <7 1>; |
| 94 | reg = <3>; | 94 | reg = <3>; |
| 95 | device_type = "ethernet-phy"; | 95 | device_type = "ethernet-phy"; |
| 96 | }; | 96 | }; |
| @@ -101,8 +101,14 @@ | |||
| 101 | model = "TSEC"; | 101 | model = "TSEC"; |
| 102 | compatible = "gianfar"; | 102 | compatible = "gianfar"; |
| 103 | reg = <24000 1000>; | 103 | reg = <24000 1000>; |
| 104 | address = [ 00 00 0C 00 00 FD ]; | 104 | /* |
| 105 | interrupts = <d 2 e 2 12 2>; | 105 | * address is deprecated and will be removed |
| 106 | * in 2.6.25. Only recent versions of | ||
| 107 | * U-Boot support local-mac-address, however. | ||
| 108 | */ | ||
| 109 | address = [ 00 00 00 00 00 00 ]; | ||
| 110 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 111 | interrupts = <1d 2 1e 2 22 2>; | ||
| 106 | interrupt-parent = <&mpic>; | 112 | interrupt-parent = <&mpic>; |
| 107 | phy-handle = <&phy0>; | 113 | phy-handle = <&phy0>; |
| 108 | }; | 114 | }; |
| @@ -114,8 +120,14 @@ | |||
| 114 | model = "TSEC"; | 120 | model = "TSEC"; |
| 115 | compatible = "gianfar"; | 121 | compatible = "gianfar"; |
| 116 | reg = <25000 1000>; | 122 | reg = <25000 1000>; |
| 117 | address = [ 00 00 0C 00 01 FD ]; | 123 | /* |
| 118 | interrupts = <13 2 14 2 18 2>; | 124 | * address is deprecated and will be removed |
| 125 | * in 2.6.25. Only recent versions of | ||
| 126 | * U-Boot support local-mac-address, however. | ||
| 127 | */ | ||
| 128 | address = [ 00 00 00 00 00 00 ]; | ||
| 129 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 130 | interrupts = <23 2 24 2 28 2>; | ||
| 119 | interrupt-parent = <&mpic>; | 131 | interrupt-parent = <&mpic>; |
| 120 | phy-handle = <&phy1>; | 132 | phy-handle = <&phy1>; |
| 121 | }; | 133 | }; |
| @@ -132,79 +144,79 @@ | |||
| 132 | interrupt-map = < | 144 | interrupt-map = < |
| 133 | 145 | ||
| 134 | /* IDSEL 0x2 */ | 146 | /* IDSEL 0x2 */ |
| 135 | 1000 0 0 1 &mpic 31 1 | 147 | 1000 0 0 1 &mpic 1 1 |
| 136 | 1000 0 0 2 &mpic 32 1 | 148 | 1000 0 0 2 &mpic 2 1 |
| 137 | 1000 0 0 3 &mpic 33 1 | 149 | 1000 0 0 3 &mpic 3 1 |
| 138 | 1000 0 0 4 &mpic 34 1 | 150 | 1000 0 0 4 &mpic 4 1 |
| 139 | 151 | ||
| 140 | /* IDSEL 0x3 */ | 152 | /* IDSEL 0x3 */ |
| 141 | 1800 0 0 1 &mpic 34 1 | 153 | 1800 0 0 1 &mpic 4 1 |
| 142 | 1800 0 0 2 &mpic 31 1 | 154 | 1800 0 0 2 &mpic 1 1 |
| 143 | 1800 0 0 3 &mpic 32 1 | 155 | 1800 0 0 3 &mpic 2 1 |
| 144 | 1800 0 0 4 &mpic 33 1 | 156 | 1800 0 0 4 &mpic 3 1 |
| 145 | 157 | ||
| 146 | /* IDSEL 0x4 */ | 158 | /* IDSEL 0x4 */ |
| 147 | 2000 0 0 1 &mpic 33 1 | 159 | 2000 0 0 1 &mpic 3 1 |
| 148 | 2000 0 0 2 &mpic 34 1 | 160 | 2000 0 0 2 &mpic 4 1 |
| 149 | 2000 0 0 3 &mpic 31 1 | 161 | 2000 0 0 3 &mpic 1 1 |
| 150 | 2000 0 0 4 &mpic 32 1 | 162 | 2000 0 0 4 &mpic 2 1 |
| 151 | 163 | ||
| 152 | /* IDSEL 0x5 */ | 164 | /* IDSEL 0x5 */ |
| 153 | 2800 0 0 1 &mpic 32 1 | 165 | 2800 0 0 1 &mpic 2 1 |
| 154 | 2800 0 0 2 &mpic 33 1 | 166 | 2800 0 0 2 &mpic 3 1 |
| 155 | 2800 0 0 3 &mpic 34 1 | 167 | 2800 0 0 3 &mpic 4 1 |
| 156 | 2800 0 0 4 &mpic 31 1 | 168 | 2800 0 0 4 &mpic 1 1 |
| 157 | 169 | ||
| 158 | /* IDSEL 12 */ | 170 | /* IDSEL 12 */ |
| 159 | 6000 0 0 1 &mpic 31 1 | 171 | 6000 0 0 1 &mpic 1 1 |
| 160 | 6000 0 0 2 &mpic 32 1 | 172 | 6000 0 0 2 &mpic 2 1 |
| 161 | 6000 0 0 3 &mpic 33 1 | 173 | 6000 0 0 3 &mpic 3 1 |
| 162 | 6000 0 0 4 &mpic 34 1 | 174 | 6000 0 0 4 &mpic 4 1 |
| 163 | 175 | ||
| 164 | /* IDSEL 13 */ | 176 | /* IDSEL 13 */ |
| 165 | 6800 0 0 1 &mpic 34 1 | 177 | 6800 0 0 1 &mpic 4 1 |
| 166 | 6800 0 0 2 &mpic 31 1 | 178 | 6800 0 0 2 &mpic 1 1 |
| 167 | 6800 0 0 3 &mpic 32 1 | 179 | 6800 0 0 3 &mpic 2 1 |
| 168 | 6800 0 0 4 &mpic 33 1 | 180 | 6800 0 0 4 &mpic 3 1 |
| 169 | 181 | ||
| 170 | /* IDSEL 14*/ | 182 | /* IDSEL 14*/ |
| 171 | 7000 0 0 1 &mpic 33 1 | 183 | 7000 0 0 1 &mpic 3 1 |
| 172 | 7000 0 0 2 &mpic 34 1 | 184 | 7000 0 0 2 &mpic 4 1 |
| 173 | 7000 0 0 3 &mpic 31 1 | 185 | 7000 0 0 3 &mpic 1 1 |
| 174 | 7000 0 0 4 &mpic 32 1 | 186 | 7000 0 0 4 &mpic 2 1 |
| 175 | 187 | ||
| 176 | /* IDSEL 15 */ | 188 | /* IDSEL 15 */ |
| 177 | 7800 0 0 1 &mpic 32 1 | 189 | 7800 0 0 1 &mpic 2 1 |
| 178 | 7800 0 0 2 &mpic 33 1 | 190 | 7800 0 0 2 &mpic 3 1 |
| 179 | 7800 0 0 3 &mpic 34 1 | 191 | 7800 0 0 3 &mpic 4 1 |
| 180 | 7800 0 0 4 &mpic 31 1 | 192 | 7800 0 0 4 &mpic 1 1 |
| 181 | 193 | ||
| 182 | /* IDSEL 18 */ | 194 | /* IDSEL 18 */ |
| 183 | 9000 0 0 1 &mpic 31 1 | 195 | 9000 0 0 1 &mpic 1 1 |
| 184 | 9000 0 0 2 &mpic 32 1 | 196 | 9000 0 0 2 &mpic 2 1 |
| 185 | 9000 0 0 3 &mpic 33 1 | 197 | 9000 0 0 3 &mpic 3 1 |
| 186 | 9000 0 0 4 &mpic 34 1 | 198 | 9000 0 0 4 &mpic 4 1 |
| 187 | 199 | ||
| 188 | /* IDSEL 19 */ | 200 | /* IDSEL 19 */ |
| 189 | 9800 0 0 1 &mpic 34 1 | 201 | 9800 0 0 1 &mpic 4 1 |
| 190 | 9800 0 0 2 &mpic 31 1 | 202 | 9800 0 0 2 &mpic 1 1 |
| 191 | 9800 0 0 3 &mpic 32 1 | 203 | 9800 0 0 3 &mpic 2 1 |
| 192 | 9800 0 0 4 &mpic 33 1 | 204 | 9800 0 0 4 &mpic 3 1 |
| 193 | 205 | ||
| 194 | /* IDSEL 20 */ | 206 | /* IDSEL 20 */ |
| 195 | a000 0 0 1 &mpic 33 1 | 207 | a000 0 0 1 &mpic 3 1 |
| 196 | a000 0 0 2 &mpic 34 1 | 208 | a000 0 0 2 &mpic 4 1 |
| 197 | a000 0 0 3 &mpic 31 1 | 209 | a000 0 0 3 &mpic 1 1 |
| 198 | a000 0 0 4 &mpic 32 1 | 210 | a000 0 0 4 &mpic 2 1 |
| 199 | 211 | ||
| 200 | /* IDSEL 21 */ | 212 | /* IDSEL 21 */ |
| 201 | a800 0 0 1 &mpic 32 1 | 213 | a800 0 0 1 &mpic 2 1 |
| 202 | a800 0 0 2 &mpic 33 1 | 214 | a800 0 0 2 &mpic 3 1 |
| 203 | a800 0 0 3 &mpic 34 1 | 215 | a800 0 0 3 &mpic 4 1 |
| 204 | a800 0 0 4 &mpic 31 1>; | 216 | a800 0 0 4 &mpic 1 1>; |
| 205 | 217 | ||
| 206 | interrupt-parent = <&mpic>; | 218 | interrupt-parent = <&mpic>; |
| 207 | interrupts = <8 0>; | 219 | interrupts = <18 2>; |
| 208 | bus-range = <0 0>; | 220 | bus-range = <0 0>; |
| 209 | ranges = <02000000 0 80000000 80000000 0 20000000 | 221 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 210 | 01000000 0 00000000 e2000000 0 01000000>; | 222 | 01000000 0 00000000 e2000000 0 01000000>; |
| @@ -234,7 +246,7 @@ | |||
| 234 | interrupt-controller; | 246 | interrupt-controller; |
| 235 | #address-cells = <0>; | 247 | #address-cells = <0>; |
| 236 | #interrupt-cells = <2>; | 248 | #interrupt-cells = <2>; |
| 237 | interrupts = <1e 0>; | 249 | interrupts = <2e 2>; |
| 238 | interrupt-parent = <&mpic>; | 250 | interrupt-parent = <&mpic>; |
| 239 | reg = <90c00 80>; | 251 | reg = <90c00 80>; |
| 240 | built-in; | 252 | built-in; |
| @@ -275,7 +287,13 @@ | |||
| 275 | model = "FCC"; | 287 | model = "FCC"; |
| 276 | device-id = <2>; | 288 | device-id = <2>; |
| 277 | reg = <91320 20 88500 100 913a0 30>; | 289 | reg = <91320 20 88500 100 913a0 30>; |
| 278 | mac-address = [ 00 00 0C 00 02 FD ]; | 290 | /* |
| 291 | * mac-address is deprecated and will be removed | ||
| 292 | * in 2.6.25. Only recent versions of | ||
| 293 | * U-Boot support local-mac-address, however. | ||
| 294 | */ | ||
| 295 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 296 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 279 | clock-setup = <ff00ffff 250000>; | 297 | clock-setup = <ff00ffff 250000>; |
| 280 | rx-clock = <15>; | 298 | rx-clock = <15>; |
| 281 | tx-clock = <16>; | 299 | tx-clock = <16>; |
| @@ -290,7 +308,13 @@ | |||
| 290 | model = "FCC"; | 308 | model = "FCC"; |
| 291 | device-id = <3>; | 309 | device-id = <3>; |
| 292 | reg = <91340 20 88600 100 913d0 30>; | 310 | reg = <91340 20 88600 100 913d0 30>; |
| 293 | mac-address = [ 00 00 0C 00 03 FD ]; | 311 | /* |
| 312 | * mac-address is deprecated and will be removed | ||
| 313 | * in 2.6.25. Only recent versions of | ||
| 314 | * U-Boot support local-mac-address, however. | ||
| 315 | */ | ||
| 316 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 317 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 294 | clock-setup = <ffff00ff 3700>; | 318 | clock-setup = <ffff00ff 3700>; |
| 295 | rx-clock = <17>; | 319 | rx-clock = <17>; |
| 296 | tx-clock = <18>; | 320 | tx-clock = <18>; |
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index a123ec9456bc..6bb18f2807a8 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts | |||
| @@ -61,7 +61,7 @@ | |||
| 61 | compatible = "fsl,8568-memory-controller"; | 61 | compatible = "fsl,8568-memory-controller"; |
| 62 | reg = <2000 1000>; | 62 | reg = <2000 1000>; |
| 63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | interrupts = <2 2>; | 64 | interrupts = <12 2>; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | l2-cache-controller@20000 { | 67 | l2-cache-controller@20000 { |
| @@ -70,14 +70,14 @@ | |||
| 70 | cache-line-size = <20>; // 32 bytes | 70 | cache-line-size = <20>; // 32 bytes |
| 71 | cache-size = <80000>; // L2, 512K | 71 | cache-size = <80000>; // L2, 512K |
| 72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
| 73 | interrupts = <0 2>; | 73 | interrupts = <10 2>; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | i2c@3000 { | 76 | i2c@3000 { |
| 77 | device_type = "i2c"; | 77 | device_type = "i2c"; |
| 78 | compatible = "fsl-i2c"; | 78 | compatible = "fsl-i2c"; |
| 79 | reg = <3000 100>; | 79 | reg = <3000 100>; |
| 80 | interrupts = <1b 2>; | 80 | interrupts = <2b 2>; |
| 81 | interrupt-parent = <&mpic>; | 81 | interrupt-parent = <&mpic>; |
| 82 | dfsrr; | 82 | dfsrr; |
| 83 | }; | 83 | }; |
| @@ -86,7 +86,7 @@ | |||
| 86 | device_type = "i2c"; | 86 | device_type = "i2c"; |
| 87 | compatible = "fsl-i2c"; | 87 | compatible = "fsl-i2c"; |
| 88 | reg = <3100 100>; | 88 | reg = <3100 100>; |
| 89 | interrupts = <1b 2>; | 89 | interrupts = <2b 2>; |
| 90 | interrupt-parent = <&mpic>; | 90 | interrupt-parent = <&mpic>; |
| 91 | dfsrr; | 91 | dfsrr; |
| 92 | }; | 92 | }; |
| @@ -99,25 +99,25 @@ | |||
| 99 | reg = <24520 20>; | 99 | reg = <24520 20>; |
| 100 | phy0: ethernet-phy@0 { | 100 | phy0: ethernet-phy@0 { |
| 101 | interrupt-parent = <&mpic>; | 101 | interrupt-parent = <&mpic>; |
| 102 | interrupts = <31 1>; | 102 | interrupts = <1 1>; |
| 103 | reg = <0>; | 103 | reg = <0>; |
| 104 | device_type = "ethernet-phy"; | 104 | device_type = "ethernet-phy"; |
| 105 | }; | 105 | }; |
| 106 | phy1: ethernet-phy@1 { | 106 | phy1: ethernet-phy@1 { |
| 107 | interrupt-parent = <&mpic>; | 107 | interrupt-parent = <&mpic>; |
| 108 | interrupts = <32 1>; | 108 | interrupts = <2 1>; |
| 109 | reg = <1>; | 109 | reg = <1>; |
| 110 | device_type = "ethernet-phy"; | 110 | device_type = "ethernet-phy"; |
| 111 | }; | 111 | }; |
| 112 | phy2: ethernet-phy@2 { | 112 | phy2: ethernet-phy@2 { |
| 113 | interrupt-parent = <&mpic>; | 113 | interrupt-parent = <&mpic>; |
| 114 | interrupts = <31 1>; | 114 | interrupts = <1 1>; |
| 115 | reg = <2>; | 115 | reg = <2>; |
| 116 | device_type = "ethernet-phy"; | 116 | device_type = "ethernet-phy"; |
| 117 | }; | 117 | }; |
| 118 | phy3: ethernet-phy@3 { | 118 | phy3: ethernet-phy@3 { |
| 119 | interrupt-parent = <&mpic>; | 119 | interrupt-parent = <&mpic>; |
| 120 | interrupts = <32 1>; | 120 | interrupts = <2 1>; |
| 121 | reg = <3>; | 121 | reg = <3>; |
| 122 | device_type = "ethernet-phy"; | 122 | device_type = "ethernet-phy"; |
| 123 | }; | 123 | }; |
| @@ -130,8 +130,14 @@ | |||
| 130 | model = "eTSEC"; | 130 | model = "eTSEC"; |
| 131 | compatible = "gianfar"; | 131 | compatible = "gianfar"; |
| 132 | reg = <24000 1000>; | 132 | reg = <24000 1000>; |
| 133 | /* | ||
| 134 | * mac-address is deprecated and will be removed | ||
| 135 | * in 2.6.25. Only recent versions of | ||
| 136 | * U-Boot support local-mac-address, however. | ||
| 137 | */ | ||
| 133 | mac-address = [ 00 00 00 00 00 00 ]; | 138 | mac-address = [ 00 00 00 00 00 00 ]; |
| 134 | interrupts = <d 2 e 2 12 2>; | 139 | local-mac-address = [ 00 00 00 00 00 00 ]; |
| 140 | interrupts = <1d 2 1e 2 22 2>; | ||
| 135 | interrupt-parent = <&mpic>; | 141 | interrupt-parent = <&mpic>; |
| 136 | phy-handle = <&phy2>; | 142 | phy-handle = <&phy2>; |
| 137 | }; | 143 | }; |
| @@ -143,8 +149,14 @@ | |||
| 143 | model = "eTSEC"; | 149 | model = "eTSEC"; |
| 144 | compatible = "gianfar"; | 150 | compatible = "gianfar"; |
| 145 | reg = <25000 1000>; | 151 | reg = <25000 1000>; |
| 146 | mac-address = [ 00 00 00 00 00 00]; | 152 | /* |
| 147 | interrupts = <13 2 14 2 18 2>; | 153 | * mac-address is deprecated and will be removed |
| 154 | * in 2.6.25. Only recent versions of | ||
| 155 | * U-Boot support local-mac-address, however. | ||
| 156 | */ | ||
| 157 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 158 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 159 | interrupts = <23 2 24 2 28 2>; | ||
| 148 | interrupt-parent = <&mpic>; | 160 | interrupt-parent = <&mpic>; |
| 149 | phy-handle = <&phy3>; | 161 | phy-handle = <&phy3>; |
| 150 | }; | 162 | }; |
| @@ -154,7 +166,7 @@ | |||
| 154 | compatible = "ns16550"; | 166 | compatible = "ns16550"; |
| 155 | reg = <4500 100>; | 167 | reg = <4500 100>; |
| 156 | clock-frequency = <0>; | 168 | clock-frequency = <0>; |
| 157 | interrupts = <1a 2>; | 169 | interrupts = <2a 2>; |
| 158 | interrupt-parent = <&mpic>; | 170 | interrupt-parent = <&mpic>; |
| 159 | }; | 171 | }; |
| 160 | 172 | ||
| @@ -163,7 +175,7 @@ | |||
| 163 | compatible = "ns16550"; | 175 | compatible = "ns16550"; |
| 164 | reg = <4600 100>; | 176 | reg = <4600 100>; |
| 165 | clock-frequency = <0>; | 177 | clock-frequency = <0>; |
| 166 | interrupts = <1a 2>; | 178 | interrupts = <2a 2>; |
| 167 | interrupt-parent = <&mpic>; | 179 | interrupt-parent = <&mpic>; |
| 168 | }; | 180 | }; |
| 169 | 181 | ||
| @@ -172,7 +184,7 @@ | |||
| 172 | model = "SEC2"; | 184 | model = "SEC2"; |
| 173 | compatible = "talitos"; | 185 | compatible = "talitos"; |
| 174 | reg = <30000 f000>; | 186 | reg = <30000 f000>; |
| 175 | interrupts = <1d 2>; | 187 | interrupts = <2d 2>; |
| 176 | interrupt-parent = <&mpic>; | 188 | interrupt-parent = <&mpic>; |
| 177 | num-channels = <4>; | 189 | num-channels = <4>; |
| 178 | channel-fifo-len = <18>; | 190 | channel-fifo-len = <18>; |
| @@ -300,7 +312,13 @@ | |||
| 300 | reg = <2000 200>; | 312 | reg = <2000 200>; |
| 301 | interrupts = <20>; | 313 | interrupts = <20>; |
| 302 | interrupt-parent = <&qeic>; | 314 | interrupt-parent = <&qeic>; |
| 303 | mac-address = [ 00 04 9f 00 23 23 ]; | 315 | /* |
| 316 | * mac-address is deprecated and will be removed | ||
| 317 | * in 2.6.25. Only recent versions of | ||
| 318 | * U-Boot support local-mac-address, however. | ||
| 319 | */ | ||
| 320 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 321 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 304 | rx-clock = <0>; | 322 | rx-clock = <0>; |
| 305 | tx-clock = <19>; | 323 | tx-clock = <19>; |
| 306 | phy-handle = <&qe_phy0>; | 324 | phy-handle = <&qe_phy0>; |
| @@ -316,7 +334,13 @@ | |||
| 316 | reg = <3000 200>; | 334 | reg = <3000 200>; |
| 317 | interrupts = <21>; | 335 | interrupts = <21>; |
| 318 | interrupt-parent = <&qeic>; | 336 | interrupt-parent = <&qeic>; |
| 319 | mac-address = [ 00 11 22 33 44 55 ]; | 337 | /* |
| 338 | * mac-address is deprecated and will be removed | ||
| 339 | * in 2.6.25. Only recent versions of | ||
| 340 | * U-Boot support local-mac-address, however. | ||
| 341 | */ | ||
| 342 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 343 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 320 | rx-clock = <0>; | 344 | rx-clock = <0>; |
| 321 | tx-clock = <14>; | 345 | tx-clock = <14>; |
| 322 | phy-handle = <&qe_phy1>; | 346 | phy-handle = <&qe_phy1>; |
| @@ -335,25 +359,25 @@ | |||
| 335 | * gianfar's MDIO bus */ | 359 | * gianfar's MDIO bus */ |
| 336 | qe_phy0: ethernet-phy@00 { | 360 | qe_phy0: ethernet-phy@00 { |
| 337 | interrupt-parent = <&mpic>; | 361 | interrupt-parent = <&mpic>; |
| 338 | interrupts = <31 1>; | 362 | interrupts = <1 1>; |
| 339 | reg = <0>; | 363 | reg = <0>; |
| 340 | device_type = "ethernet-phy"; | 364 | device_type = "ethernet-phy"; |
| 341 | }; | 365 | }; |
| 342 | qe_phy1: ethernet-phy@01 { | 366 | qe_phy1: ethernet-phy@01 { |
| 343 | interrupt-parent = <&mpic>; | 367 | interrupt-parent = <&mpic>; |
| 344 | interrupts = <32 1>; | 368 | interrupts = <2 1>; |
| 345 | reg = <1>; | 369 | reg = <1>; |
| 346 | device_type = "ethernet-phy"; | 370 | device_type = "ethernet-phy"; |
| 347 | }; | 371 | }; |
| 348 | qe_phy2: ethernet-phy@02 { | 372 | qe_phy2: ethernet-phy@02 { |
| 349 | interrupt-parent = <&mpic>; | 373 | interrupt-parent = <&mpic>; |
| 350 | interrupts = <31 1>; | 374 | interrupts = <1 1>; |
| 351 | reg = <2>; | 375 | reg = <2>; |
| 352 | device_type = "ethernet-phy"; | 376 | device_type = "ethernet-phy"; |
| 353 | }; | 377 | }; |
| 354 | qe_phy3: ethernet-phy@03 { | 378 | qe_phy3: ethernet-phy@03 { |
| 355 | interrupt-parent = <&mpic>; | 379 | interrupt-parent = <&mpic>; |
| 356 | interrupts = <32 1>; | 380 | interrupts = <2 1>; |
| 357 | reg = <3>; | 381 | reg = <3>; |
| 358 | device_type = "ethernet-phy"; | 382 | device_type = "ethernet-phy"; |
| 359 | }; | 383 | }; |
| @@ -367,7 +391,7 @@ | |||
| 367 | reg = <80 80>; | 391 | reg = <80 80>; |
| 368 | built-in; | 392 | built-in; |
| 369 | big-endian; | 393 | big-endian; |
| 370 | interrupts = <1e 2 1e 2>; //high:30 low:30 | 394 | interrupts = <2e 2 2e 2>; //high:30 low:30 |
| 371 | interrupt-parent = <&mpic>; | 395 | interrupt-parent = <&mpic>; |
| 372 | }; | 396 | }; |
| 373 | 397 | ||
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 260b264c869e..db56a02b748f 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts | |||
| @@ -56,8 +56,12 @@ | |||
| 56 | #size-cells = <1>; | 56 | #size-cells = <1>; |
| 57 | #interrupt-cells = <2>; | 57 | #interrupt-cells = <2>; |
| 58 | device_type = "soc"; | 58 | device_type = "soc"; |
| 59 | ranges = <0 f8000000 00100000>; | 59 | ranges = <00001000 f8001000 000ff000 |
| 60 | reg = <f8000000 00100000>; // CCSRBAR 1M | 60 | 80000000 80000000 20000000 |
| 61 | e2000000 e2000000 00100000 | ||
| 62 | a0000000 a0000000 20000000 | ||
| 63 | e3000000 e3000000 00100000>; | ||
| 64 | reg = <f8000000 00001000>; // CCSRBAR | ||
| 61 | bus-frequency = <0>; | 65 | bus-frequency = <0>; |
| 62 | 66 | ||
| 63 | i2c@3000 { | 67 | i2c@3000 { |
| @@ -86,25 +90,25 @@ | |||
| 86 | reg = <24520 20>; | 90 | reg = <24520 20>; |
| 87 | phy0: ethernet-phy@0 { | 91 | phy0: ethernet-phy@0 { |
| 88 | interrupt-parent = <&mpic>; | 92 | interrupt-parent = <&mpic>; |
| 89 | interrupts = <4a 1>; | 93 | interrupts = <a 1>; |
| 90 | reg = <0>; | 94 | reg = <0>; |
| 91 | device_type = "ethernet-phy"; | 95 | device_type = "ethernet-phy"; |
| 92 | }; | 96 | }; |
| 93 | phy1: ethernet-phy@1 { | 97 | phy1: ethernet-phy@1 { |
| 94 | interrupt-parent = <&mpic>; | 98 | interrupt-parent = <&mpic>; |
| 95 | interrupts = <4a 1>; | 99 | interrupts = <a 1>; |
| 96 | reg = <1>; | 100 | reg = <1>; |
| 97 | device_type = "ethernet-phy"; | 101 | device_type = "ethernet-phy"; |
| 98 | }; | 102 | }; |
| 99 | phy2: ethernet-phy@2 { | 103 | phy2: ethernet-phy@2 { |
| 100 | interrupt-parent = <&mpic>; | 104 | interrupt-parent = <&mpic>; |
| 101 | interrupts = <4a 1>; | 105 | interrupts = <a 1>; |
| 102 | reg = <2>; | 106 | reg = <2>; |
| 103 | device_type = "ethernet-phy"; | 107 | device_type = "ethernet-phy"; |
| 104 | }; | 108 | }; |
| 105 | phy3: ethernet-phy@3 { | 109 | phy3: ethernet-phy@3 { |
| 106 | interrupt-parent = <&mpic>; | 110 | interrupt-parent = <&mpic>; |
| 107 | interrupts = <4a 1>; | 111 | interrupts = <a 1>; |
| 108 | reg = <3>; | 112 | reg = <3>; |
| 109 | device_type = "ethernet-phy"; | 113 | device_type = "ethernet-phy"; |
| 110 | }; | 114 | }; |
| @@ -117,7 +121,13 @@ | |||
| 117 | model = "TSEC"; | 121 | model = "TSEC"; |
| 118 | compatible = "gianfar"; | 122 | compatible = "gianfar"; |
| 119 | reg = <24000 1000>; | 123 | reg = <24000 1000>; |
| 120 | mac-address = [ 00 E0 0C 00 73 00 ]; | 124 | /* |
| 125 | * mac-address is deprecated and will be removed | ||
| 126 | * in 2.6.25. Only recent versions of | ||
| 127 | * U-Boot support local-mac-address, however. | ||
| 128 | */ | ||
| 129 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 130 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 121 | interrupts = <1d 2 1e 2 22 2>; | 131 | interrupts = <1d 2 1e 2 22 2>; |
| 122 | interrupt-parent = <&mpic>; | 132 | interrupt-parent = <&mpic>; |
| 123 | phy-handle = <&phy0>; | 133 | phy-handle = <&phy0>; |
| @@ -130,7 +140,13 @@ | |||
| 130 | model = "TSEC"; | 140 | model = "TSEC"; |
| 131 | compatible = "gianfar"; | 141 | compatible = "gianfar"; |
| 132 | reg = <25000 1000>; | 142 | reg = <25000 1000>; |
| 133 | mac-address = [ 00 E0 0C 00 73 01 ]; | 143 | /* |
| 144 | * mac-address is deprecated and will be removed | ||
| 145 | * in 2.6.25. Only recent versions of | ||
| 146 | * U-Boot support local-mac-address, however. | ||
| 147 | */ | ||
| 148 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 149 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 134 | interrupts = <23 2 24 2 28 2>; | 150 | interrupts = <23 2 24 2 28 2>; |
| 135 | interrupt-parent = <&mpic>; | 151 | interrupt-parent = <&mpic>; |
| 136 | phy-handle = <&phy1>; | 152 | phy-handle = <&phy1>; |
| @@ -143,7 +159,13 @@ | |||
| 143 | model = "TSEC"; | 159 | model = "TSEC"; |
| 144 | compatible = "gianfar"; | 160 | compatible = "gianfar"; |
| 145 | reg = <26000 1000>; | 161 | reg = <26000 1000>; |
| 146 | mac-address = [ 00 E0 0C 00 02 FD ]; | 162 | /* |
| 163 | * mac-address is deprecated and will be removed | ||
| 164 | * in 2.6.25. Only recent versions of | ||
| 165 | * U-Boot support local-mac-address, however. | ||
| 166 | */ | ||
| 167 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 168 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 147 | interrupts = <1F 2 20 2 21 2>; | 169 | interrupts = <1F 2 20 2 21 2>; |
| 148 | interrupt-parent = <&mpic>; | 170 | interrupt-parent = <&mpic>; |
| 149 | phy-handle = <&phy2>; | 171 | phy-handle = <&phy2>; |
| @@ -156,7 +178,13 @@ | |||
| 156 | model = "TSEC"; | 178 | model = "TSEC"; |
| 157 | compatible = "gianfar"; | 179 | compatible = "gianfar"; |
| 158 | reg = <27000 1000>; | 180 | reg = <27000 1000>; |
| 159 | mac-address = [ 00 E0 0C 00 03 FD ]; | 181 | /* |
| 182 | * mac-address is deprecated and will be removed | ||
| 183 | * in 2.6.25. Only recent versions of | ||
| 184 | * U-Boot support local-mac-address, however. | ||
| 185 | */ | ||
| 186 | mac-address = [ 00 00 00 00 00 00 ]; | ||
| 187 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 160 | interrupts = <25 2 26 2 27 2>; | 188 | interrupts = <25 2 26 2 27 2>; |
| 161 | interrupt-parent = <&mpic>; | 189 | interrupt-parent = <&mpic>; |
| 162 | phy-handle = <&phy3>; | 190 | phy-handle = <&phy3>; |
| @@ -186,7 +214,7 @@ | |||
| 186 | #size-cells = <2>; | 214 | #size-cells = <2>; |
| 187 | #address-cells = <3>; | 215 | #address-cells = <3>; |
| 188 | reg = <8000 1000>; | 216 | reg = <8000 1000>; |
| 189 | bus-range = <0 fe>; | 217 | bus-range = <0 ff>; |
| 190 | ranges = <02000000 0 80000000 80000000 0 20000000 | 218 | ranges = <02000000 0 80000000 80000000 0 20000000 |
| 191 | 01000000 0 00000000 e2000000 0 00100000>; | 219 | 01000000 0 00000000 e2000000 0 00100000>; |
| 192 | clock-frequency = <1fca055>; | 220 | clock-frequency = <1fca055>; |
| @@ -285,17 +313,84 @@ | |||
| 285 | f800 0 0 3 &i8259 0 0 | 313 | f800 0 0 3 &i8259 0 0 |
| 286 | f800 0 0 4 &i8259 0 0 | 314 | f800 0 0 4 &i8259 0 0 |
| 287 | >; | 315 | >; |
| 288 | i8259: i8259@4d0 { | 316 | uli1575@0 { |
| 289 | clock-frequency = <0>; | 317 | reg = <0 0 0 0 0>; |
| 290 | interrupt-controller; | 318 | #size-cells = <2>; |
| 291 | device_type = "interrupt-controller"; | 319 | #address-cells = <3>; |
| 292 | #address-cells = <0>; | 320 | ranges = <02000000 0 80000000 |
| 293 | #interrupt-cells = <2>; | 321 | 02000000 0 80000000 |
| 294 | built-in; | 322 | 0 20000000 |
| 295 | compatible = "chrp,iic"; | 323 | 01000000 0 00000000 |
| 296 | big-endian; | 324 | 01000000 0 00000000 |
| 297 | interrupts = <49 2>; | 325 | 0 00100000>; |
| 298 | interrupt-parent = <&mpic>; | 326 | |
| 327 | pci_bridge@0 { | ||
| 328 | reg = <0 0 0 0 0>; | ||
| 329 | #size-cells = <2>; | ||
| 330 | #address-cells = <3>; | ||
| 331 | ranges = <02000000 0 80000000 | ||
| 332 | 02000000 0 80000000 | ||
| 333 | 0 20000000 | ||
| 334 | 01000000 0 00000000 | ||
| 335 | 01000000 0 00000000 | ||
| 336 | 0 00100000>; | ||
| 337 | |||
| 338 | isa@1e { | ||
| 339 | device_type = "isa"; | ||
| 340 | #interrupt-cells = <2>; | ||
| 341 | #size-cells = <1>; | ||
| 342 | #address-cells = <2>; | ||
| 343 | reg = <f000 0 0 0 0>; | ||
| 344 | ranges = <1 0 01000000 0 0 | ||
| 345 | 00001000>; | ||
| 346 | interrupt-parent = <&i8259>; | ||
| 347 | |||
| 348 | i8259: interrupt-controller@20 { | ||
| 349 | reg = <1 20 2 | ||
| 350 | 1 a0 2 | ||
| 351 | 1 4d0 2>; | ||
| 352 | clock-frequency = <0>; | ||
| 353 | interrupt-controller; | ||
| 354 | device_type = "interrupt-controller"; | ||
| 355 | #address-cells = <0>; | ||
| 356 | #interrupt-cells = <2>; | ||
| 357 | built-in; | ||
| 358 | compatible = "chrp,iic"; | ||
| 359 | interrupts = <9 2>; | ||
| 360 | interrupt-parent = | ||
| 361 | <&mpic>; | ||
| 362 | }; | ||
| 363 | |||
| 364 | i8042@60 { | ||
| 365 | #size-cells = <0>; | ||
| 366 | #address-cells = <1>; | ||
| 367 | reg = <1 60 1 1 64 1>; | ||
| 368 | interrupts = <1 3 c 3>; | ||
| 369 | interrupt-parent = | ||
| 370 | <&i8259>; | ||
| 371 | |||
| 372 | keyboard@0 { | ||
| 373 | reg = <0>; | ||
| 374 | compatible = "pnpPNP,303"; | ||
| 375 | }; | ||
| 376 | |||
| 377 | mouse@1 { | ||
| 378 | reg = <1>; | ||
| 379 | compatible = "pnpPNP,f03"; | ||
| 380 | }; | ||
| 381 | }; | ||
| 382 | |||
| 383 | rtc@70 { | ||
| 384 | compatible = | ||
| 385 | "pnpPNP,b00"; | ||
| 386 | reg = <1 70 2>; | ||
| 387 | }; | ||
| 388 | |||
| 389 | gpio@400 { | ||
| 390 | reg = <1 400 80>; | ||
| 391 | }; | ||
| 392 | }; | ||
| 393 | }; | ||
| 299 | }; | 394 | }; |
| 300 | 395 | ||
| 301 | }; | 396 | }; |
| @@ -316,10 +411,10 @@ | |||
| 316 | interrupt-map-mask = <f800 0 0 7>; | 411 | interrupt-map-mask = <f800 0 0 7>; |
| 317 | interrupt-map = < | 412 | interrupt-map = < |
| 318 | /* IDSEL 0x0 */ | 413 | /* IDSEL 0x0 */ |
| 319 | 0000 0 0 1 &mpic 44 1 | 414 | 0000 0 0 1 &mpic 4 1 |
| 320 | 0000 0 0 2 &mpic 45 1 | 415 | 0000 0 0 2 &mpic 5 1 |
| 321 | 0000 0 0 3 &mpic 46 1 | 416 | 0000 0 0 3 &mpic 6 1 |
| 322 | 0000 0 0 4 &mpic 47 1 | 417 | 0000 0 0 4 &mpic 7 1 |
| 323 | >; | 418 | >; |
| 324 | }; | 419 | }; |
| 325 | 420 | ||
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts index c0d06fd12927..e5e7726ddb03 100644 --- a/arch/powerpc/boot/dts/mpc866ads.dts +++ b/arch/powerpc/boot/dts/mpc866ads.dts | |||
| @@ -15,12 +15,10 @@ | |||
| 15 | compatible = "mpc8xx"; | 15 | compatible = "mpc8xx"; |
| 16 | #address-cells = <1>; | 16 | #address-cells = <1>; |
| 17 | #size-cells = <1>; | 17 | #size-cells = <1>; |
| 18 | linux,phandle = <100>; | ||
| 19 | 18 | ||
| 20 | cpus { | 19 | cpus { |
| 21 | #address-cells = <1>; | 20 | #address-cells = <1>; |
| 22 | #size-cells = <0>; | 21 | #size-cells = <0>; |
| 23 | linux,phandle = <200>; | ||
| 24 | 22 | ||
| 25 | PowerPC,866@0 { | 23 | PowerPC,866@0 { |
| 26 | device_type = "cpu"; | 24 | device_type = "cpu"; |
| @@ -34,14 +32,12 @@ | |||
| 34 | clock-frequency = <0>; | 32 | clock-frequency = <0>; |
| 35 | 32-bit; | 33 | 32-bit; |
| 36 | interrupts = <f 2>; // decrementer interrupt | 34 | interrupts = <f 2>; // decrementer interrupt |
| 37 | interrupt-parent = <ff000000>; | 35 | interrupt-parent = <&Mpc8xx_pic>; |
| 38 | linux,phandle = <201>; | ||
| 39 | }; | 36 | }; |
| 40 | }; | 37 | }; |
| 41 | 38 | ||
| 42 | memory { | 39 | memory { |
| 43 | device_type = "memory"; | 40 | device_type = "memory"; |
| 44 | linux,phandle = <300>; | ||
| 45 | reg = <00000000 800000>; | 41 | reg = <00000000 800000>; |
| 46 | }; | 42 | }; |
| 47 | 43 | ||
| @@ -57,11 +53,9 @@ | |||
| 57 | device_type = "mdio"; | 53 | device_type = "mdio"; |
| 58 | compatible = "fs_enet"; | 54 | compatible = "fs_enet"; |
| 59 | reg = <e80 8>; | 55 | reg = <e80 8>; |
| 60 | linux,phandle = <e80>; | ||
| 61 | #address-cells = <1>; | 56 | #address-cells = <1>; |
| 62 | #size-cells = <0>; | 57 | #size-cells = <0>; |
| 63 | ethernet-phy@f { | 58 | phy: ethernet-phy@f { |
| 64 | linux,phandle = <e800f>; | ||
| 65 | reg = <f>; | 59 | reg = <f>; |
| 66 | device_type = "ethernet-phy"; | 60 | device_type = "ethernet-phy"; |
| 67 | }; | 61 | }; |
| @@ -75,12 +69,11 @@ | |||
| 75 | reg = <e00 188>; | 69 | reg = <e00 188>; |
| 76 | mac-address = [ 00 00 0C 00 01 FD ]; | 70 | mac-address = [ 00 00 0C 00 01 FD ]; |
| 77 | interrupts = <3 1>; | 71 | interrupts = <3 1>; |
| 78 | interrupt-parent = <ff000000>; | 72 | interrupt-parent = <&Mpc8xx_pic>; |
| 79 | phy-handle = <e800f>; | 73 | phy-handle = <&Phy>; |
| 80 | }; | 74 | }; |
| 81 | 75 | ||
| 82 | pic@ff000000 { | 76 | mpc8xx_pic: pic@ff000000 { |
| 83 | linux,phandle = <ff000000>; | ||
| 84 | interrupt-controller; | 77 | interrupt-controller; |
| 85 | #address-cells = <0>; | 78 | #address-cells = <0>; |
| 86 | #interrupt-cells = <2>; | 79 | #interrupt-cells = <2>; |
| @@ -91,7 +84,6 @@ | |||
| 91 | }; | 84 | }; |
| 92 | 85 | ||
| 93 | cpm@ff000000 { | 86 | cpm@ff000000 { |
| 94 | linux,phandle = <ff000000>; | ||
| 95 | #address-cells = <1>; | 87 | #address-cells = <1>; |
| 96 | #size-cells = <1>; | 88 | #size-cells = <1>; |
| 97 | #interrupt-cells = <2>; | 89 | #interrupt-cells = <2>; |
| @@ -102,15 +94,14 @@ | |||
| 102 | command-proc = <9c0>; | 94 | command-proc = <9c0>; |
| 103 | brg-frequency = <0>; | 95 | brg-frequency = <0>; |
| 104 | interrupts = <0 2>; // cpm error interrupt | 96 | interrupts = <0 2>; // cpm error interrupt |
| 105 | interrupt-parent = <930>; | 97 | interrupt-parent = <&Cpm_pic>; |
| 106 | 98 | ||
| 107 | pic@930 { | 99 | cpm_pic: pic@930 { |
| 108 | linux,phandle = <930>; | ||
| 109 | interrupt-controller; | 100 | interrupt-controller; |
| 110 | #address-cells = <0>; | 101 | #address-cells = <0>; |
| 111 | #interrupt-cells = <2>; | 102 | #interrupt-cells = <2>; |
| 112 | interrupts = <5 2 0 2>; | 103 | interrupts = <5 2 0 2>; |
| 113 | interrupt-parent = <ff000000>; | 104 | interrupt-parent = <&Mpc8xx_pic>; |
| 114 | reg = <930 20>; | 105 | reg = <930 20>; |
| 115 | built-in; | 106 | built-in; |
| 116 | device_type = "cpm-pic"; | 107 | device_type = "cpm-pic"; |
| @@ -128,7 +119,7 @@ | |||
| 128 | tx-clock = <1>; | 119 | tx-clock = <1>; |
| 129 | current-speed = <0>; | 120 | current-speed = <0>; |
| 130 | interrupts = <4 3>; | 121 | interrupts = <4 3>; |
| 131 | interrupt-parent = <930>; | 122 | interrupt-parent = <&Cpm_pic>; |
| 132 | }; | 123 | }; |
| 133 | 124 | ||
| 134 | smc@a90 { | 125 | smc@a90 { |
| @@ -142,7 +133,7 @@ | |||
| 142 | tx-clock = <2>; | 133 | tx-clock = <2>; |
| 143 | current-speed = <0>; | 134 | current-speed = <0>; |
| 144 | interrupts = <3 3>; | 135 | interrupts = <3 3>; |
| 145 | interrupt-parent = <930>; | 136 | interrupt-parent = <&Cpm_pic>; |
| 146 | }; | 137 | }; |
| 147 | 138 | ||
| 148 | scc@a00 { | 139 | scc@a00 { |
| @@ -153,7 +144,7 @@ | |||
| 153 | reg = <a00 18 3c00 80>; | 144 | reg = <a00 18 3c00 80>; |
| 154 | mac-address = [ 00 00 0C 00 03 FD ]; | 145 | mac-address = [ 00 00 0C 00 03 FD ]; |
| 155 | interrupts = <1e 3>; | 146 | interrupts = <1e 3>; |
| 156 | interrupt-parent = <930>; | 147 | interrupt-parent = <&Cpm_pic>; |
| 157 | }; | 148 | }; |
| 158 | }; | 149 | }; |
| 159 | }; | 150 | }; |
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index 110bf6170603..dc7ab9c80611 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts | |||
| @@ -15,12 +15,10 @@ | |||
| 15 | compatible = "mpc8xx"; | 15 | compatible = "mpc8xx"; |
| 16 | #address-cells = <1>; | 16 | #address-cells = <1>; |
| 17 | #size-cells = <1>; | 17 | #size-cells = <1>; |
| 18 | linux,phandle = <100>; | ||
| 19 | 18 | ||
| 20 | cpus { | 19 | cpus { |
| 21 | #address-cells = <1>; | 20 | #address-cells = <1>; |
| 22 | #size-cells = <0>; | 21 | #size-cells = <0>; |
| 23 | linux,phandle = <200>; | ||
| 24 | 22 | ||
| 25 | PowerPC,885@0 { | 23 | PowerPC,885@0 { |
| 26 | device_type = "cpu"; | 24 | device_type = "cpu"; |
| @@ -34,14 +32,12 @@ | |||
| 34 | clock-frequency = <0>; | 32 | clock-frequency = <0>; |
| 35 | 32-bit; | 33 | 32-bit; |
| 36 | interrupts = <f 2>; // decrementer interrupt | 34 | interrupts = <f 2>; // decrementer interrupt |
| 37 | interrupt-parent = <ff000000>; | 35 | interrupt-parent = <&Mpc8xx_pic>; |
| 38 | linux,phandle = <201>; | ||
| 39 | }; | 36 | }; |
| 40 | }; | 37 | }; |
| 41 | 38 | ||
| 42 | memory { | 39 | memory { |
| 43 | device_type = "memory"; | 40 | device_type = "memory"; |
| 44 | linux,phandle = <300>; | ||
| 45 | reg = <00000000 800000>; | 41 | reg = <00000000 800000>; |
| 46 | }; | 42 | }; |
| 47 | 43 | ||
| @@ -57,21 +53,17 @@ | |||
| 57 | device_type = "mdio"; | 53 | device_type = "mdio"; |
| 58 | compatible = "fs_enet"; | 54 | compatible = "fs_enet"; |
| 59 | reg = <e80 8>; | 55 | reg = <e80 8>; |
| 60 | linux,phandle = <e80>; | ||
| 61 | #address-cells = <1>; | 56 | #address-cells = <1>; |
| 62 | #size-cells = <0>; | 57 | #size-cells = <0>; |
| 63 | ethernet-phy@0 { | 58 | Phy0: ethernet-phy@0 { |
| 64 | linux,phandle = <e8000>; | ||
| 65 | reg = <0>; | 59 | reg = <0>; |
| 66 | device_type = "ethernet-phy"; | 60 | device_type = "ethernet-phy"; |
| 67 | }; | 61 | }; |
| 68 | ethernet-phy@1 { | 62 | Phy1: ethernet-phy@1 { |
| 69 | linux,phandle = <e8001>; | ||
| 70 | reg = <1>; | 63 | reg = <1>; |
| 71 | device_type = "ethernet-phy"; | 64 | device_type = "ethernet-phy"; |
| 72 | }; | 65 | }; |
| 73 | ethernet-phy@2 { | 66 | Phy2: ethernet-phy@2 { |
| 74 | linux,phandle = <e8002>; | ||
| 75 | reg = <2>; | 67 | reg = <2>; |
| 76 | device_type = "ethernet-phy"; | 68 | device_type = "ethernet-phy"; |
| 77 | }; | 69 | }; |
| @@ -85,8 +77,8 @@ | |||
| 85 | reg = <e00 188>; | 77 | reg = <e00 188>; |
| 86 | mac-address = [ 00 00 0C 00 01 FD ]; | 78 | mac-address = [ 00 00 0C 00 01 FD ]; |
| 87 | interrupts = <3 1>; | 79 | interrupts = <3 1>; |
| 88 | interrupt-parent = <ff000000>; | 80 | interrupt-parent = <&Mpc8xx_pic>; |
| 89 | phy-handle = <e8000>; | 81 | phy-handle = <&Phy1>; |
| 90 | }; | 82 | }; |
| 91 | 83 | ||
| 92 | fec@1e00 { | 84 | fec@1e00 { |
| @@ -97,12 +89,11 @@ | |||
| 97 | reg = <1e00 188>; | 89 | reg = <1e00 188>; |
| 98 | mac-address = [ 00 00 0C 00 02 FD ]; | 90 | mac-address = [ 00 00 0C 00 02 FD ]; |
| 99 | interrupts = <7 1>; | 91 | interrupts = <7 1>; |
| 100 | interrupt-parent = <ff000000>; | 92 | interrupt-parent = <&Mpc8xx_pic>; |
| 101 | phy-handle = <e8001>; | 93 | phy-handle = <&Phy2>; |
| 102 | }; | 94 | }; |
| 103 | 95 | ||
| 104 | pic@ff000000 { | 96 | Mpc8xx_pic: pic@ff000000 { |
| 105 | linux,phandle = <ff000000>; | ||
| 106 | interrupt-controller; | 97 | interrupt-controller; |
| 107 | #address-cells = <0>; | 98 | #address-cells = <0>; |
| 108 | #interrupt-cells = <2>; | 99 | #interrupt-cells = <2>; |
| @@ -112,8 +103,18 @@ | |||
| 112 | compatible = "CPM"; | 103 | compatible = "CPM"; |
| 113 | }; | 104 | }; |
| 114 | 105 | ||
| 106 | pcmcia@0080 { | ||
| 107 | #address-cells = <3>; | ||
| 108 | #interrupt-cells = <1>; | ||
| 109 | #size-cells = <2>; | ||
| 110 | compatible = "fsl,pq-pcmcia"; | ||
| 111 | device_type = "pcmcia"; | ||
| 112 | reg = <80 80>; | ||
| 113 | interrupt-parent = <&Mpc8xx_pic>; | ||
| 114 | interrupts = <d 1>; | ||
| 115 | }; | ||
| 116 | |||
| 115 | cpm@ff000000 { | 117 | cpm@ff000000 { |
| 116 | linux,phandle = <ff000000>; | ||
| 117 | #address-cells = <1>; | 118 | #address-cells = <1>; |
| 118 | #size-cells = <1>; | 119 | #size-cells = <1>; |
| 119 | #interrupt-cells = <2>; | 120 | #interrupt-cells = <2>; |
| @@ -124,15 +125,14 @@ | |||
| 124 | command-proc = <9c0>; | 125 | command-proc = <9c0>; |
| 125 | brg-frequency = <0>; | 126 | brg-frequency = <0>; |
| 126 | interrupts = <0 2>; // cpm error interrupt | 127 | interrupts = <0 2>; // cpm error interrupt |
| 127 | interrupt-parent = <930>; | 128 | interrupt-parent = <&Cpm_pic>; |
| 128 | 129 | ||
| 129 | pic@930 { | 130 | Cpm_pic: pic@930 { |
| 130 | linux,phandle = <930>; | ||
| 131 | interrupt-controller; | 131 | interrupt-controller; |
| 132 | #address-cells = <0>; | 132 | #address-cells = <0>; |
| 133 | #interrupt-cells = <2>; | 133 | #interrupt-cells = <2>; |
| 134 | interrupts = <5 2 0 2>; | 134 | interrupts = <5 2 0 2>; |
| 135 | interrupt-parent = <ff000000>; | 135 | interrupt-parent = <&Mpc8xx_pic>; |
| 136 | reg = <930 20>; | 136 | reg = <930 20>; |
| 137 | built-in; | 137 | built-in; |
| 138 | device_type = "cpm-pic"; | 138 | device_type = "cpm-pic"; |
| @@ -150,7 +150,7 @@ | |||
| 150 | tx-clock = <1>; | 150 | tx-clock = <1>; |
| 151 | current-speed = <0>; | 151 | current-speed = <0>; |
| 152 | interrupts = <4 3>; | 152 | interrupts = <4 3>; |
| 153 | interrupt-parent = <930>; | 153 | interrupt-parent = <&Cpm_pic>; |
| 154 | }; | 154 | }; |
| 155 | 155 | ||
| 156 | smc@a90 { | 156 | smc@a90 { |
| @@ -164,7 +164,7 @@ | |||
| 164 | tx-clock = <2>; | 164 | tx-clock = <2>; |
| 165 | current-speed = <0>; | 165 | current-speed = <0>; |
| 166 | interrupts = <3 3>; | 166 | interrupts = <3 3>; |
| 167 | interrupt-parent = <930>; | 167 | interrupt-parent = <&Cpm_pic>; |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | scc@a40 { | 170 | scc@a40 { |
| @@ -175,8 +175,8 @@ | |||
| 175 | reg = <a40 18 3e00 80>; | 175 | reg = <a40 18 3e00 80>; |
| 176 | mac-address = [ 00 00 0C 00 03 FD ]; | 176 | mac-address = [ 00 00 0C 00 03 FD ]; |
| 177 | interrupts = <1c 3>; | 177 | interrupts = <1c 3>; |
| 178 | interrupt-parent = <930>; | 178 | interrupt-parent = <&Cpm_pic>; |
| 179 | phy-handle = <e8002>; | 179 | phy-handle = <&Phy2>; |
| 180 | }; | 180 | }; |
| 181 | }; | 181 | }; |
| 182 | }; | 182 | }; |
diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts index 568965a022b9..699d0df574d5 100644 --- a/arch/powerpc/boot/dts/prpmc2800.dts +++ b/arch/powerpc/boot/dts/prpmc2800.dts | |||
| @@ -309,7 +309,7 @@ | |||
| 309 | }; | 309 | }; |
| 310 | 310 | ||
| 311 | chosen { | 311 | chosen { |
| 312 | bootargs = "ip=on console=ttyMM0"; | 312 | bootargs = "ip=on"; |
| 313 | linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; | 313 | linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; |
| 314 | }; | 314 | }; |
| 315 | }; | 315 | }; |
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts new file mode 100644 index 000000000000..379ded282d5e --- /dev/null +++ b/arch/powerpc/boot/dts/ps3.dts | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * PS3 Game Console device tree. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | / { | ||
| 22 | model = "SonyPS3"; | ||
| 23 | compatible = "sony,ps3"; | ||
| 24 | #size-cells = <2>; | ||
| 25 | #address-cells = <2>; | ||
| 26 | |||
| 27 | chosen { | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* | ||
| 31 | * We'll get the size of the bootmem block from lv1 after startup, | ||
| 32 | * so we'll put a null entry here. | ||
| 33 | */ | ||
| 34 | |||
| 35 | memory { | ||
| 36 | device_type = "memory"; | ||
| 37 | reg = <0 0 0 0>; | ||
| 38 | }; | ||
| 39 | |||
| 40 | /* | ||
| 41 | * The boot cpu is always zero for PS3. | ||
| 42 | * | ||
| 43 | * dtc expects a clock-frequency and timebase-frequency entries, so | ||
| 44 | * we'll put a null entries here. These will be initialized after | ||
| 45 | * startup with data from lv1. | ||
| 46 | * | ||
| 47 | * Seems the only way currently to indicate a processor has multiple | ||
| 48 | * threads is with an ibm,ppc-interrupt-server#s entry. We'll put one | ||
| 49 | * here so we can bring up both of ours. See smp_setup_cpu_maps(). | ||
| 50 | */ | ||
| 51 | |||
| 52 | cpus { | ||
| 53 | #size-cells = <0>; | ||
| 54 | #address-cells = <1>; | ||
| 55 | |||
| 56 | cpu@0 { | ||
| 57 | device_type = "cpu"; | ||
| 58 | reg = <0>; | ||
| 59 | ibm,ppc-interrupt-server#s = <0 1>; | ||
| 60 | clock-frequency = <0>; | ||
| 61 | timebase-frequency = <0>; | ||
| 62 | i-cache-size = <8000>; | ||
| 63 | d-cache-size = <8000>; | ||
| 64 | i-cache-line-size = <80>; | ||
| 65 | d-cache-line-size = <80>; | ||
| 66 | }; | ||
| 67 | }; | ||
| 68 | }; | ||
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c index b1251ee7a102..75daedafd0a4 100644 --- a/arch/powerpc/boot/ebony.c +++ b/arch/powerpc/boot/ebony.c | |||
| @@ -100,28 +100,13 @@ static void ebony_fixups(void) | |||
| 100 | ibm440gp_fixup_clocks(sysclk, 6 * 1843200); | 100 | ibm440gp_fixup_clocks(sysclk, 6 * 1843200); |
| 101 | ibm44x_fixup_memsize(); | 101 | ibm44x_fixup_memsize(); |
| 102 | dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); | 102 | dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); |
| 103 | } | 103 | ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); |
| 104 | |||
| 105 | #define SPRN_DBCR0 0x134 | ||
| 106 | #define DBCR0_RST_SYSTEM 0x30000000 | ||
| 107 | |||
| 108 | static void ebony_exit(void) | ||
| 109 | { | ||
| 110 | unsigned long tmp; | ||
| 111 | |||
| 112 | asm volatile ( | ||
| 113 | "mfspr %0,%1\n" | ||
| 114 | "oris %0,%0,%2@h\n" | ||
| 115 | "mtspr %1,%0" | ||
| 116 | : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||
| 117 | ); | ||
| 118 | |||
| 119 | } | 104 | } |
| 120 | 105 | ||
| 121 | void ebony_init(void *mac0, void *mac1) | 106 | void ebony_init(void *mac0, void *mac1) |
| 122 | { | 107 | { |
| 123 | platform_ops.fixups = ebony_fixups; | 108 | platform_ops.fixups = ebony_fixups; |
| 124 | platform_ops.exit = ebony_exit; | 109 | platform_ops.exit = ibm44x_dbcr_reset; |
| 125 | ebony_mac0 = mac0; | 110 | ebony_mac0 = mac0; |
| 126 | ebony_mac1 = mac1; | 111 | ebony_mac1 = mac1; |
| 127 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 112 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 56b56a8d4b23..416dc3857bfe 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
| @@ -36,8 +36,6 @@ struct addr_range { | |||
| 36 | unsigned long size; | 36 | unsigned long size; |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); | ||
| 40 | |||
| 41 | #undef DEBUG | 39 | #undef DEBUG |
| 42 | 40 | ||
| 43 | static struct addr_range prep_kernel(void) | 41 | static struct addr_range prep_kernel(void) |
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index d16ee3e3f868..385e08b83b7e 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c | |||
| @@ -15,8 +15,7 @@ | |||
| 15 | #include "page.h" | 15 | #include "page.h" |
| 16 | #include "ops.h" | 16 | #include "ops.h" |
| 17 | 17 | ||
| 18 | typedef void *ihandle; | 18 | #include "of.h" |
| 19 | typedef void *phandle; | ||
| 20 | 19 | ||
| 21 | extern char _end[]; | 20 | extern char _end[]; |
| 22 | 21 | ||
| @@ -25,154 +24,10 @@ extern char _end[]; | |||
| 25 | #define RAM_END (512<<20) /* Fixme: use OF */ | 24 | #define RAM_END (512<<20) /* Fixme: use OF */ |
| 26 | #define ONE_MB 0x100000 | 25 | #define ONE_MB 0x100000 |
| 27 | 26 | ||
| 28 | int (*prom) (void *); | ||
| 29 | 27 | ||
| 30 | 28 | ||
| 31 | static unsigned long claim_base; | 29 | static unsigned long claim_base; |
| 32 | 30 | ||
| 33 | static int call_prom(const char *service, int nargs, int nret, ...) | ||
| 34 | { | ||
| 35 | int i; | ||
| 36 | struct prom_args { | ||
| 37 | const char *service; | ||
| 38 | int nargs; | ||
| 39 | int nret; | ||
| 40 | unsigned int args[12]; | ||
| 41 | } args; | ||
| 42 | va_list list; | ||
| 43 | |||
| 44 | args.service = service; | ||
| 45 | args.nargs = nargs; | ||
| 46 | args.nret = nret; | ||
| 47 | |||
| 48 | va_start(list, nret); | ||
| 49 | for (i = 0; i < nargs; i++) | ||
| 50 | args.args[i] = va_arg(list, unsigned int); | ||
| 51 | va_end(list); | ||
| 52 | |||
| 53 | for (i = 0; i < nret; i++) | ||
| 54 | args.args[nargs+i] = 0; | ||
| 55 | |||
| 56 | if (prom(&args) < 0) | ||
| 57 | return -1; | ||
| 58 | |||
| 59 | return (nret > 0)? args.args[nargs]: 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int call_prom_ret(const char *service, int nargs, int nret, | ||
| 63 | unsigned int *rets, ...) | ||
| 64 | { | ||
| 65 | int i; | ||
| 66 | struct prom_args { | ||
| 67 | const char *service; | ||
| 68 | int nargs; | ||
| 69 | int nret; | ||
| 70 | unsigned int args[12]; | ||
| 71 | } args; | ||
| 72 | va_list list; | ||
| 73 | |||
| 74 | args.service = service; | ||
| 75 | args.nargs = nargs; | ||
| 76 | args.nret = nret; | ||
| 77 | |||
| 78 | va_start(list, rets); | ||
| 79 | for (i = 0; i < nargs; i++) | ||
| 80 | args.args[i] = va_arg(list, unsigned int); | ||
| 81 | va_end(list); | ||
| 82 | |||
| 83 | for (i = 0; i < nret; i++) | ||
| 84 | args.args[nargs+i] = 0; | ||
| 85 | |||
| 86 | if (prom(&args) < 0) | ||
| 87 | return -1; | ||
| 88 | |||
| 89 | if (rets != (void *) 0) | ||
| 90 | for (i = 1; i < nret; ++i) | ||
| 91 | rets[i-1] = args.args[nargs+i]; | ||
| 92 | |||
| 93 | return (nret > 0)? args.args[nargs]: 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Older OF's require that when claiming a specific range of addresses, | ||
| 98 | * we claim the physical space in the /memory node and the virtual | ||
| 99 | * space in the chosen mmu node, and then do a map operation to | ||
| 100 | * map virtual to physical. | ||
| 101 | */ | ||
| 102 | static int need_map = -1; | ||
| 103 | static ihandle chosen_mmu; | ||
| 104 | static phandle memory; | ||
| 105 | |||
| 106 | /* returns true if s2 is a prefix of s1 */ | ||
| 107 | static int string_match(const char *s1, const char *s2) | ||
| 108 | { | ||
| 109 | for (; *s2; ++s2) | ||
| 110 | if (*s1++ != *s2) | ||
| 111 | return 0; | ||
| 112 | return 1; | ||
| 113 | } | ||
| 114 | |||
| 115 | static int check_of_version(void) | ||
| 116 | { | ||
| 117 | phandle oprom, chosen; | ||
| 118 | char version[64]; | ||
| 119 | |||
| 120 | oprom = finddevice("/openprom"); | ||
| 121 | if (oprom == (phandle) -1) | ||
| 122 | return 0; | ||
| 123 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
| 124 | return 0; | ||
| 125 | version[sizeof(version)-1] = 0; | ||
| 126 | printf("OF version = '%s'\r\n", version); | ||
| 127 | if (!string_match(version, "Open Firmware, 1.") | ||
| 128 | && !string_match(version, "FirmWorks,3.")) | ||
| 129 | return 0; | ||
| 130 | chosen = finddevice("/chosen"); | ||
| 131 | if (chosen == (phandle) -1) { | ||
| 132 | chosen = finddevice("/chosen@0"); | ||
| 133 | if (chosen == (phandle) -1) { | ||
| 134 | printf("no chosen\n"); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
| 139 | printf("no mmu\n"); | ||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||
| 143 | if (memory == (ihandle) -1) { | ||
| 144 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||
| 145 | if (memory == (ihandle) -1) { | ||
| 146 | printf("no memory node\n"); | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | printf("old OF detected\r\n"); | ||
| 151 | return 1; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void *claim(unsigned long virt, unsigned long size, unsigned long align) | ||
| 155 | { | ||
| 156 | int ret; | ||
| 157 | unsigned int result; | ||
| 158 | |||
| 159 | if (need_map < 0) | ||
| 160 | need_map = check_of_version(); | ||
| 161 | if (align || !need_map) | ||
| 162 | return (void *) call_prom("claim", 3, 1, virt, size, align); | ||
| 163 | |||
| 164 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||
| 165 | align, size, virt); | ||
| 166 | if (ret != 0 || result == -1) | ||
| 167 | return (void *) -1; | ||
| 168 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
| 169 | align, size, virt); | ||
| 170 | /* 0x12 == coherent + read/write */ | ||
| 171 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
| 172 | 0x12, size, virt, virt); | ||
| 173 | return (void *) virt; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void *of_try_claim(unsigned long size) | 31 | static void *of_try_claim(unsigned long size) |
| 177 | { | 32 | { |
| 178 | unsigned long addr = 0; | 33 | unsigned long addr = 0; |
| @@ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size) | |||
| 184 | #ifdef DEBUG | 39 | #ifdef DEBUG |
| 185 | printf(" trying: 0x%08lx\n\r", claim_base); | 40 | printf(" trying: 0x%08lx\n\r", claim_base); |
| 186 | #endif | 41 | #endif |
| 187 | addr = (unsigned long)claim(claim_base, size, 0); | 42 | addr = (unsigned long)of_claim(claim_base, size, 0); |
| 188 | if ((void *)addr != (void *)-1) | 43 | if ((void *)addr != (void *)-1) |
| 189 | break; | 44 | break; |
| 190 | } | 45 | } |
| @@ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr) | |||
| 208 | } | 63 | } |
| 209 | } | 64 | } |
| 210 | 65 | ||
| 211 | static void *of_vmlinux_alloc(unsigned long size) | ||
| 212 | { | ||
| 213 | void *p = malloc(size); | ||
| 214 | |||
| 215 | if (!p) | ||
| 216 | fatal("Can't allocate memory for kernel image!\n\r"); | ||
| 217 | |||
| 218 | return p; | ||
| 219 | } | ||
| 220 | |||
| 221 | static void of_exit(void) | ||
| 222 | { | ||
| 223 | call_prom("exit", 0, 0); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * OF device tree routines | ||
| 228 | */ | ||
| 229 | static void *of_finddevice(const char *name) | ||
| 230 | { | ||
| 231 | return (phandle) call_prom("finddevice", 1, 1, name); | ||
| 232 | } | ||
| 233 | |||
| 234 | static int of_getprop(const void *phandle, const char *name, void *buf, | ||
| 235 | const int buflen) | ||
| 236 | { | ||
| 237 | return call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||
| 238 | } | ||
| 239 | |||
| 240 | static int of_setprop(const void *phandle, const char *name, const void *buf, | ||
| 241 | const int buflen) | ||
| 242 | { | ||
| 243 | return call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||
| 244 | } | ||
| 245 | |||
| 246 | /* | ||
| 247 | * OF console routines | ||
| 248 | */ | ||
| 249 | static void *of_stdout_handle; | ||
| 250 | |||
| 251 | static int of_console_open(void) | ||
| 252 | { | ||
| 253 | void *devp; | ||
| 254 | |||
| 255 | if (((devp = finddevice("/chosen")) != NULL) | ||
| 256 | && (getprop(devp, "stdout", &of_stdout_handle, | ||
| 257 | sizeof(of_stdout_handle)) | ||
| 258 | == sizeof(of_stdout_handle))) | ||
| 259 | return 0; | ||
| 260 | |||
| 261 | return -1; | ||
| 262 | } | ||
| 263 | |||
| 264 | static void of_console_write(char *buf, int len) | ||
| 265 | { | ||
| 266 | call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||
| 267 | } | ||
| 268 | |||
| 269 | void platform_init(unsigned long a1, unsigned long a2, void *promptr) | 66 | void platform_init(unsigned long a1, unsigned long a2, void *promptr) |
| 270 | { | 67 | { |
| 271 | platform_ops.image_hdr = of_image_hdr; | 68 | platform_ops.image_hdr = of_image_hdr; |
| @@ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr) | |||
| 277 | dt_ops.getprop = of_getprop; | 74 | dt_ops.getprop = of_getprop; |
| 278 | dt_ops.setprop = of_setprop; | 75 | dt_ops.setprop = of_setprop; |
| 279 | 76 | ||
| 280 | console_ops.open = of_console_open; | 77 | of_console_init(); |
| 281 | console_ops.write = of_console_write; | ||
| 282 | 78 | ||
| 283 | prom = (int (*)(void *))promptr; | 79 | of_init(promptr); |
| 284 | loader_info.promptr = promptr; | 80 | loader_info.promptr = promptr; |
| 285 | if (a1 && a2 && a2 != 0xdeadbeef) { | 81 | if (a1 && a2 && a2 != 0xdeadbeef) { |
| 286 | loader_info.initrd_addr = a1; | 82 | loader_info.initrd_addr = a1; |
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h new file mode 100644 index 000000000000..e4c68f7391c5 --- /dev/null +++ b/arch/powerpc/boot/of.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #ifndef _PPC_BOOT_OF_H_ | ||
| 2 | #define _PPC_BOOT_OF_H_ | ||
| 3 | |||
| 4 | typedef void *phandle; | ||
| 5 | typedef void *ihandle; | ||
| 6 | |||
| 7 | void of_init(void *promptr); | ||
| 8 | int of_call_prom(const char *service, int nargs, int nret, ...); | ||
| 9 | void *of_claim(unsigned long virt, unsigned long size, unsigned long align); | ||
| 10 | void *of_vmlinux_alloc(unsigned long size); | ||
| 11 | void of_exit(void); | ||
| 12 | void *of_finddevice(const char *name); | ||
| 13 | int of_getprop(const void *phandle, const char *name, void *buf, | ||
| 14 | const int buflen); | ||
| 15 | int of_setprop(const void *phandle, const char *name, const void *buf, | ||
| 16 | const int buflen); | ||
| 17 | |||
| 18 | /* Console functions */ | ||
| 19 | void of_console_init(void); | ||
| 20 | |||
| 21 | #endif /* _PPC_BOOT_OF_H_ */ | ||
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c new file mode 100644 index 000000000000..ce0e02424453 --- /dev/null +++ b/arch/powerpc/boot/ofconsole.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | * OF console routines | ||
| 3 | * | ||
| 4 | * Copyright (C) Paul Mackerras 1997. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <stddef.h> | ||
| 12 | #include "types.h" | ||
| 13 | #include "elf.h" | ||
| 14 | #include "string.h" | ||
| 15 | #include "stdio.h" | ||
| 16 | #include "page.h" | ||
| 17 | #include "ops.h" | ||
| 18 | |||
| 19 | #include "of.h" | ||
| 20 | |||
| 21 | static void *of_stdout_handle; | ||
| 22 | |||
| 23 | static int of_console_open(void) | ||
| 24 | { | ||
| 25 | void *devp; | ||
| 26 | |||
| 27 | if (((devp = of_finddevice("/chosen")) != NULL) | ||
| 28 | && (of_getprop(devp, "stdout", &of_stdout_handle, | ||
| 29 | sizeof(of_stdout_handle)) | ||
| 30 | == sizeof(of_stdout_handle))) | ||
| 31 | return 0; | ||
| 32 | |||
| 33 | return -1; | ||
| 34 | } | ||
| 35 | |||
| 36 | static void of_console_write(const char *buf, int len) | ||
| 37 | { | ||
| 38 | of_call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||
| 39 | } | ||
| 40 | |||
| 41 | void of_console_init(void) | ||
| 42 | { | ||
| 43 | console_ops.open = of_console_open; | ||
| 44 | console_ops.write = of_console_write; | ||
| 45 | } | ||
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c new file mode 100644 index 000000000000..95b8fd69a403 --- /dev/null +++ b/arch/powerpc/boot/oflib.c | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Paul Mackerras 1997. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | #include <stddef.h> | ||
| 10 | #include "types.h" | ||
| 11 | #include "elf.h" | ||
| 12 | #include "string.h" | ||
| 13 | #include "stdio.h" | ||
| 14 | #include "page.h" | ||
| 15 | #include "ops.h" | ||
| 16 | |||
| 17 | #include "of.h" | ||
| 18 | |||
| 19 | static int (*prom) (void *); | ||
| 20 | |||
| 21 | void of_init(void *promptr) | ||
| 22 | { | ||
| 23 | prom = (int (*)(void *))promptr; | ||
| 24 | } | ||
| 25 | |||
| 26 | int of_call_prom(const char *service, int nargs, int nret, ...) | ||
| 27 | { | ||
| 28 | int i; | ||
| 29 | struct prom_args { | ||
| 30 | const char *service; | ||
| 31 | int nargs; | ||
| 32 | int nret; | ||
| 33 | unsigned int args[12]; | ||
| 34 | } args; | ||
| 35 | va_list list; | ||
| 36 | |||
| 37 | args.service = service; | ||
| 38 | args.nargs = nargs; | ||
| 39 | args.nret = nret; | ||
| 40 | |||
| 41 | va_start(list, nret); | ||
| 42 | for (i = 0; i < nargs; i++) | ||
| 43 | args.args[i] = va_arg(list, unsigned int); | ||
| 44 | va_end(list); | ||
| 45 | |||
| 46 | for (i = 0; i < nret; i++) | ||
| 47 | args.args[nargs+i] = 0; | ||
| 48 | |||
| 49 | if (prom(&args) < 0) | ||
| 50 | return -1; | ||
| 51 | |||
| 52 | return (nret > 0)? args.args[nargs]: 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int of_call_prom_ret(const char *service, int nargs, int nret, | ||
| 56 | unsigned int *rets, ...) | ||
| 57 | { | ||
| 58 | int i; | ||
| 59 | struct prom_args { | ||
| 60 | const char *service; | ||
| 61 | int nargs; | ||
| 62 | int nret; | ||
| 63 | unsigned int args[12]; | ||
| 64 | } args; | ||
| 65 | va_list list; | ||
| 66 | |||
| 67 | args.service = service; | ||
| 68 | args.nargs = nargs; | ||
| 69 | args.nret = nret; | ||
| 70 | |||
| 71 | va_start(list, rets); | ||
| 72 | for (i = 0; i < nargs; i++) | ||
| 73 | args.args[i] = va_arg(list, unsigned int); | ||
| 74 | va_end(list); | ||
| 75 | |||
| 76 | for (i = 0; i < nret; i++) | ||
| 77 | args.args[nargs+i] = 0; | ||
| 78 | |||
| 79 | if (prom(&args) < 0) | ||
| 80 | return -1; | ||
| 81 | |||
| 82 | if (rets != (void *) 0) | ||
| 83 | for (i = 1; i < nret; ++i) | ||
| 84 | rets[i-1] = args.args[nargs+i]; | ||
| 85 | |||
| 86 | return (nret > 0)? args.args[nargs]: 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* returns true if s2 is a prefix of s1 */ | ||
| 90 | static int string_match(const char *s1, const char *s2) | ||
| 91 | { | ||
| 92 | for (; *s2; ++s2) | ||
| 93 | if (*s1++ != *s2) | ||
| 94 | return 0; | ||
| 95 | return 1; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Older OF's require that when claiming a specific range of addresses, | ||
| 100 | * we claim the physical space in the /memory node and the virtual | ||
| 101 | * space in the chosen mmu node, and then do a map operation to | ||
| 102 | * map virtual to physical. | ||
| 103 | */ | ||
| 104 | static int need_map = -1; | ||
| 105 | static ihandle chosen_mmu; | ||
| 106 | static phandle memory; | ||
| 107 | |||
| 108 | static int check_of_version(void) | ||
| 109 | { | ||
| 110 | phandle oprom, chosen; | ||
| 111 | char version[64]; | ||
| 112 | |||
| 113 | oprom = of_finddevice("/openprom"); | ||
| 114 | if (oprom == (phandle) -1) | ||
| 115 | return 0; | ||
| 116 | if (of_getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
| 117 | return 0; | ||
| 118 | version[sizeof(version)-1] = 0; | ||
| 119 | printf("OF version = '%s'\r\n", version); | ||
| 120 | if (!string_match(version, "Open Firmware, 1.") | ||
| 121 | && !string_match(version, "FirmWorks,3.")) | ||
| 122 | return 0; | ||
| 123 | chosen = of_finddevice("/chosen"); | ||
| 124 | if (chosen == (phandle) -1) { | ||
| 125 | chosen = of_finddevice("/chosen@0"); | ||
| 126 | if (chosen == (phandle) -1) { | ||
| 127 | printf("no chosen\n"); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
| 132 | printf("no mmu\n"); | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | memory = (ihandle) of_call_prom("open", 1, 1, "/memory"); | ||
| 136 | if (memory == (ihandle) -1) { | ||
| 137 | memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0"); | ||
| 138 | if (memory == (ihandle) -1) { | ||
| 139 | printf("no memory node\n"); | ||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | printf("old OF detected\r\n"); | ||
| 144 | return 1; | ||
| 145 | } | ||
| 146 | |||
| 147 | void *of_claim(unsigned long virt, unsigned long size, unsigned long align) | ||
| 148 | { | ||
| 149 | int ret; | ||
| 150 | unsigned int result; | ||
| 151 | |||
| 152 | if (need_map < 0) | ||
| 153 | need_map = check_of_version(); | ||
| 154 | if (align || !need_map) | ||
| 155 | return (void *) of_call_prom("claim", 3, 1, virt, size, align); | ||
| 156 | |||
| 157 | ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||
| 158 | align, size, virt); | ||
| 159 | if (ret != 0 || result == -1) | ||
| 160 | return (void *) -1; | ||
| 161 | ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
| 162 | align, size, virt); | ||
| 163 | /* 0x12 == coherent + read/write */ | ||
| 164 | ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
| 165 | 0x12, size, virt, virt); | ||
| 166 | return (void *) virt; | ||
| 167 | } | ||
| 168 | |||
| 169 | void *of_vmlinux_alloc(unsigned long size) | ||
| 170 | { | ||
| 171 | void *p = malloc(size); | ||
| 172 | |||
| 173 | if (!p) | ||
| 174 | fatal("Can't allocate memory for kernel image!\n\r"); | ||
| 175 | |||
| 176 | return p; | ||
| 177 | } | ||
| 178 | |||
| 179 | void of_exit(void) | ||
| 180 | { | ||
| 181 | of_call_prom("exit", 0, 0); | ||
| 182 | } | ||
| 183 | |||
| 184 | /* | ||
| 185 | * OF device tree routines | ||
| 186 | */ | ||
| 187 | void *of_finddevice(const char *name) | ||
| 188 | { | ||
| 189 | return (phandle) of_call_prom("finddevice", 1, 1, name); | ||
| 190 | } | ||
| 191 | |||
| 192 | int of_getprop(const void *phandle, const char *name, void *buf, | ||
| 193 | const int buflen) | ||
| 194 | { | ||
| 195 | return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||
| 196 | } | ||
| 197 | |||
| 198 | int of_setprop(const void *phandle, const char *name, const void *buf, | ||
| 199 | const int buflen) | ||
| 200 | { | ||
| 201 | return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||
| 202 | } | ||
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 959124f3f9af..86077066cd7c 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #define MAX_PATH_LEN 256 | 19 | #define MAX_PATH_LEN 256 |
| 20 | #define MAX_PROP_LEN 256 /* What should this be? */ | 20 | #define MAX_PROP_LEN 256 /* What should this be? */ |
| 21 | 21 | ||
| 22 | typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5); | ||
| 23 | |||
| 22 | /* Platform specific operations */ | 24 | /* Platform specific operations */ |
| 23 | struct platform_ops { | 25 | struct platform_ops { |
| 24 | void (*fixups)(void); | 26 | void (*fixups)(void); |
| @@ -51,7 +53,7 @@ extern struct dt_ops dt_ops; | |||
| 51 | /* Console operations */ | 53 | /* Console operations */ |
| 52 | struct console_ops { | 54 | struct console_ops { |
| 53 | int (*open)(void); | 55 | int (*open)(void); |
| 54 | void (*write)(char *buf, int len); | 56 | void (*write)(const char *buf, int len); |
| 55 | void (*edit_cmdline)(char *buf, int len); | 57 | void (*edit_cmdline)(char *buf, int len); |
| 56 | void (*close)(void); | 58 | void (*close)(void); |
| 57 | void *data; | 59 | void *data; |
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S new file mode 100644 index 000000000000..1a6d64a68df5 --- /dev/null +++ b/arch/powerpc/boot/ps3-head.S | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | /* | ||
| 2 | * PS3 bootwrapper entry. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "ppc_asm.h" | ||
| 22 | |||
| 23 | .text | ||
| 24 | |||
| 25 | /* | ||
| 26 | * __system_reset_overlay - The PS3 first stage entry. | ||
| 27 | * | ||
| 28 | * The bootwraper build script copies the 0x100 bytes at symbol | ||
| 29 | * __system_reset_overlay to offset 0x100 of the rom image. | ||
| 30 | * | ||
| 31 | * The PS3 has a single processor with two threads. | ||
| 32 | */ | ||
| 33 | |||
| 34 | .globl __system_reset_overlay | ||
| 35 | __system_reset_overlay: | ||
| 36 | |||
| 37 | /* Switch to 32-bit mode. */ | ||
| 38 | |||
| 39 | mfmsr r9 | ||
| 40 | clrldi r9,r9,1 | ||
| 41 | mtmsrd r9 | ||
| 42 | nop | ||
| 43 | |||
| 44 | /* Get thread number in r3 and branch. */ | ||
| 45 | |||
| 46 | mfspr r3, 0x88 | ||
| 47 | cntlzw. r3, r3 | ||
| 48 | li r4, 0 | ||
| 49 | li r5, 0 | ||
| 50 | beq 1f | ||
| 51 | |||
| 52 | /* Secondary goes to __secondary_hold in kernel. */ | ||
| 53 | |||
| 54 | li r4, 0x60 | ||
| 55 | mtctr r4 | ||
| 56 | bctr | ||
| 57 | |||
| 58 | /* Primary delays then goes to _zimage_start in wrapper. */ | ||
| 59 | 1: | ||
| 60 | or 31, 31, 31 /* db16cyc */ | ||
| 61 | or 31, 31, 31 /* db16cyc */ | ||
| 62 | |||
| 63 | lis r4, _zimage_start@ha | ||
| 64 | addi r4, r4, _zimage_start@l | ||
| 65 | mtctr r4 | ||
| 66 | bctr | ||
| 67 | |||
| 68 | /* | ||
| 69 | * __system_reset_kernel - Place holder for the kernel reset vector. | ||
| 70 | * | ||
| 71 | * The bootwrapper build script copies 0x100 bytes from offset 0x100 | ||
| 72 | * of the rom image to the symbol __system_reset_kernel. At runtime | ||
| 73 | * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel | ||
| 74 | * to ram address 0x100. This symbol must occupy 0x100 bytes. | ||
| 75 | */ | ||
| 76 | |||
| 77 | .globl __system_reset_kernel | ||
| 78 | __system_reset_kernel: | ||
| 79 | |||
| 80 | . = __system_reset_kernel + 0x100 | ||
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S new file mode 100644 index 000000000000..c8b7df3210d1 --- /dev/null +++ b/arch/powerpc/boot/ps3-hvcall.S | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /* | ||
| 2 | * PS3 bootwrapper hvcalls. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "ppc_asm.h" | ||
| 22 | |||
| 23 | /* | ||
| 24 | * The PS3 hypervisor uses a 64 bit "C" language calling convention. | ||
| 25 | * The routines here marshal arguments between the 32 bit wrapper | ||
| 26 | * program and the 64 bit hvcalls. | ||
| 27 | * | ||
| 28 | * wrapper lv1 | ||
| 29 | * 32-bit (h,l) 64-bit | ||
| 30 | * | ||
| 31 | * 1: r3,r4 <-> r3 | ||
| 32 | * 2: r5,r6 <-> r4 | ||
| 33 | * 3: r7,r8 <-> r5 | ||
| 34 | * 4: r9,r10 <-> r6 | ||
| 35 | * 5: 8(r1),12(r1) <-> r7 | ||
| 36 | * 6: 16(r1),20(r1) <-> r8 | ||
| 37 | * 7: 24(r1),28(r1) <-> r9 | ||
| 38 | * 8: 32(r1),36(r1) <-> r10 | ||
| 39 | * | ||
| 40 | */ | ||
| 41 | |||
| 42 | .macro GLOBAL name | ||
| 43 | .section ".text" | ||
| 44 | .balign 4 | ||
| 45 | .globl \name | ||
| 46 | \name: | ||
| 47 | .endm | ||
| 48 | |||
| 49 | .macro NO_SUPPORT name | ||
| 50 | GLOBAL \name | ||
| 51 | b ps3_no_support | ||
| 52 | .endm | ||
| 53 | |||
| 54 | .macro HVCALL num | ||
| 55 | li r11, \num | ||
| 56 | .long 0x44000022 | ||
| 57 | extsw r3, r3 | ||
| 58 | .endm | ||
| 59 | |||
| 60 | .macro SAVE_LR offset=4 | ||
| 61 | mflr r0 | ||
| 62 | stw r0, \offset(r1) | ||
| 63 | .endm | ||
| 64 | |||
| 65 | .macro LOAD_LR offset=4 | ||
| 66 | lwz r0, \offset(r1) | ||
| 67 | mtlr r0 | ||
| 68 | .endm | ||
| 69 | |||
| 70 | .macro LOAD_64_REG target,high,low | ||
| 71 | sldi r11, \high, 32 | ||
| 72 | or \target, r11, \low | ||
| 73 | .endm | ||
| 74 | |||
| 75 | .macro LOAD_64_STACK target,offset | ||
| 76 | ld \target, \offset(r1) | ||
| 77 | .endm | ||
| 78 | |||
| 79 | .macro LOAD_R3 | ||
| 80 | LOAD_64_REG r3,r3,r4 | ||
| 81 | .endm | ||
| 82 | |||
| 83 | .macro LOAD_R4 | ||
| 84 | LOAD_64_REG r4,r5,r6 | ||
| 85 | .endm | ||
| 86 | |||
| 87 | .macro LOAD_R5 | ||
| 88 | LOAD_64_REG r5,r7,r8 | ||
| 89 | .endm | ||
| 90 | |||
| 91 | .macro LOAD_R6 | ||
| 92 | LOAD_64_REG r6,r9,r10 | ||
| 93 | .endm | ||
| 94 | |||
| 95 | .macro LOAD_R7 | ||
| 96 | LOAD_64_STACK r7,8 | ||
| 97 | .endm | ||
| 98 | |||
| 99 | .macro LOAD_R8 | ||
| 100 | LOAD_64_STACK r8,16 | ||
| 101 | .endm | ||
| 102 | |||
| 103 | .macro LOAD_R9 | ||
| 104 | LOAD_64_STACK r9,24 | ||
| 105 | .endm | ||
| 106 | |||
| 107 | .macro LOAD_R10 | ||
| 108 | LOAD_64_STACK r10,32 | ||
| 109 | .endm | ||
| 110 | |||
| 111 | .macro LOAD_REGS_0 | ||
| 112 | stwu 1,-16(1) | ||
| 113 | stw 3, 8(1) | ||
| 114 | .endm | ||
| 115 | |||
| 116 | .macro LOAD_REGS_5 | ||
| 117 | LOAD_R3 | ||
| 118 | LOAD_R4 | ||
| 119 | LOAD_R5 | ||
| 120 | LOAD_R6 | ||
| 121 | LOAD_R7 | ||
| 122 | .endm | ||
| 123 | |||
| 124 | .macro LOAD_REGS_6 | ||
| 125 | LOAD_REGS_5 | ||
| 126 | LOAD_R8 | ||
| 127 | .endm | ||
| 128 | |||
| 129 | .macro LOAD_REGS_8 | ||
| 130 | LOAD_REGS_6 | ||
| 131 | LOAD_R9 | ||
| 132 | LOAD_R10 | ||
| 133 | .endm | ||
| 134 | |||
| 135 | .macro STORE_REGS_0_1 | ||
| 136 | lwz r11, 8(r1) | ||
| 137 | std r4, 0(r11) | ||
| 138 | mr r4, r3 | ||
| 139 | li r3, 0 | ||
| 140 | addi r1,r1,16 | ||
| 141 | .endm | ||
| 142 | |||
| 143 | .macro STORE_REGS_5_2 | ||
| 144 | lwz r11, 16(r1) | ||
| 145 | std r4, 0(r11) | ||
| 146 | lwz r11, 24(r1) | ||
| 147 | std r5, 0(r11) | ||
| 148 | .endm | ||
| 149 | |||
| 150 | .macro STORE_REGS_6_1 | ||
| 151 | lwz r11, 24(r1) | ||
| 152 | std r4, 0(r11) | ||
| 153 | .endm | ||
| 154 | |||
| 155 | GLOBAL lv1_get_logical_ppe_id | ||
| 156 | SAVE_LR | ||
| 157 | LOAD_REGS_0 | ||
| 158 | HVCALL 69 | ||
| 159 | STORE_REGS_0_1 | ||
| 160 | LOAD_LR | ||
| 161 | blr | ||
| 162 | |||
| 163 | GLOBAL lv1_get_logical_partition_id | ||
| 164 | SAVE_LR | ||
| 165 | LOAD_REGS_0 | ||
| 166 | HVCALL 74 | ||
| 167 | STORE_REGS_0_1 | ||
| 168 | LOAD_LR | ||
| 169 | blr | ||
| 170 | |||
| 171 | GLOBAL lv1_get_repository_node_value | ||
| 172 | SAVE_LR | ||
| 173 | LOAD_REGS_5 | ||
| 174 | HVCALL 91 | ||
| 175 | STORE_REGS_5_2 | ||
| 176 | LOAD_LR | ||
| 177 | blr | ||
| 178 | |||
| 179 | GLOBAL lv1_panic | ||
| 180 | SAVE_LR | ||
| 181 | LOAD_REGS_8 | ||
| 182 | HVCALL 255 | ||
| 183 | LOAD_LR | ||
| 184 | blr | ||
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c new file mode 100644 index 000000000000..893d59339c26 --- /dev/null +++ b/arch/powerpc/boot/ps3.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* | ||
| 2 | * PS3 bootwrapper support. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <stdarg.h> | ||
| 22 | #include <stddef.h> | ||
| 23 | #include "types.h" | ||
| 24 | #include "elf.h" | ||
| 25 | #include "string.h" | ||
| 26 | #include "stdio.h" | ||
| 27 | #include "page.h" | ||
| 28 | #include "ops.h" | ||
| 29 | |||
| 30 | extern s64 lv1_panic(u64 in_1); | ||
| 31 | extern s64 lv1_get_logical_partition_id(u64 *out_1); | ||
| 32 | extern s64 lv1_get_logical_ppe_id(u64 *out_1); | ||
| 33 | extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3, | ||
| 34 | u64 in_4, u64 in_5, u64 *out_1, u64 *out_2); | ||
| 35 | |||
| 36 | #ifdef DEBUG | ||
| 37 | #define DBG(fmt...) printf(fmt) | ||
| 38 | #else | ||
| 39 | static inline int __attribute__ ((format (printf, 1, 2))) DBG( | ||
| 40 | const char *fmt, ...) {return 0;} | ||
| 41 | #endif | ||
| 42 | |||
| 43 | BSS_STACK(4096); | ||
| 44 | |||
| 45 | /* A buffer that may be edited by tools operating on a zImage binary so as to | ||
| 46 | * edit the command line passed to vmlinux (by setting /chosen/bootargs). | ||
| 47 | * The buffer is put in it's own section so that tools may locate it easier. | ||
| 48 | */ | ||
| 49 | static char cmdline[COMMAND_LINE_SIZE] | ||
| 50 | __attribute__((__section__("__builtin_cmdline"))); | ||
| 51 | |||
| 52 | static void prep_cmdline(void *chosen) | ||
| 53 | { | ||
| 54 | if (cmdline[0] == '\0') | ||
| 55 | getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); | ||
| 56 | else | ||
| 57 | setprop_str(chosen, "bootargs", cmdline); | ||
| 58 | |||
| 59 | printf("cmdline: '%s'\n", cmdline); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void ps3_console_write(const char *buf, int len) | ||
| 63 | { | ||
| 64 | } | ||
| 65 | |||
| 66 | static void ps3_exit(void) | ||
| 67 | { | ||
| 68 | printf("ps3_exit\n"); | ||
| 69 | |||
| 70 | /* lv1_panic will shutdown the lpar. */ | ||
| 71 | |||
| 72 | lv1_panic(0); /* zero = do not reboot */ | ||
| 73 | while (1); | ||
| 74 | } | ||
| 75 | |||
| 76 | static int ps3_repository_read_rm_size(u64 *rm_size) | ||
| 77 | { | ||
| 78 | s64 result; | ||
| 79 | u64 lpar_id; | ||
| 80 | u64 ppe_id; | ||
| 81 | u64 v2; | ||
| 82 | |||
| 83 | result = lv1_get_logical_partition_id(&lpar_id); | ||
| 84 | |||
| 85 | if (result) | ||
| 86 | return -1; | ||
| 87 | |||
| 88 | result = lv1_get_logical_ppe_id(&ppe_id); | ||
| 89 | |||
| 90 | if (result) | ||
| 91 | return -1; | ||
| 92 | |||
| 93 | /* | ||
| 94 | * n1: 0000000062690000 : ....bi.. | ||
| 95 | * n2: 7075000000000000 : pu...... | ||
| 96 | * n3: 0000000000000001 : ........ | ||
| 97 | * n4: 726d5f73697a6500 : rm_size. | ||
| 98 | */ | ||
| 99 | |||
| 100 | result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL, | ||
| 101 | 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size, | ||
| 102 | &v2); | ||
| 103 | |||
| 104 | printf("%s:%d: ppe_id %lu \n", __func__, __LINE__, | ||
| 105 | (unsigned long)ppe_id); | ||
| 106 | printf("%s:%d: lpar_id %lu \n", __func__, __LINE__, | ||
| 107 | (unsigned long)lpar_id); | ||
| 108 | printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size); | ||
| 109 | |||
| 110 | return result ? -1 : 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | void ps3_copy_vectors(void) | ||
| 114 | { | ||
| 115 | extern char __system_reset_kernel[]; | ||
| 116 | |||
| 117 | memcpy((void *)0x100, __system_reset_kernel, 0x100); | ||
| 118 | flush_cache((void *)0x100, 0x100); | ||
| 119 | } | ||
| 120 | |||
| 121 | void platform_init(void) | ||
| 122 | { | ||
| 123 | extern char _end[]; | ||
| 124 | extern char _dtb_start[]; | ||
| 125 | extern char _initrd_start[]; | ||
| 126 | extern char _initrd_end[]; | ||
| 127 | const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */ | ||
| 128 | void *chosen; | ||
| 129 | unsigned long ft_addr; | ||
| 130 | u64 rm_size; | ||
| 131 | |||
| 132 | console_ops.write = ps3_console_write; | ||
| 133 | platform_ops.exit = ps3_exit; | ||
| 134 | |||
| 135 | printf("\n-- PS3 bootwrapper --\n"); | ||
| 136 | |||
| 137 | simple_alloc_init(_end, heapsize, 32, 64); | ||
| 138 | ft_init(_dtb_start, 0, 4); | ||
| 139 | |||
| 140 | chosen = finddevice("/chosen"); | ||
| 141 | |||
| 142 | ps3_repository_read_rm_size(&rm_size); | ||
| 143 | dt_fixup_memory(0, rm_size); | ||
| 144 | |||
| 145 | if (_initrd_end > _initrd_start) { | ||
| 146 | setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start)); | ||
| 147 | setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end)); | ||
| 148 | } | ||
| 149 | |||
| 150 | prep_cmdline(chosen); | ||
| 151 | |||
| 152 | ft_addr = dt_ops.finalize(); | ||
| 153 | |||
| 154 | ps3_copy_vectors(); | ||
| 155 | |||
| 156 | printf(" flat tree at 0x%lx\n\r", ft_addr); | ||
| 157 | |||
| 158 | ((kernel_entry_t)0)(ft_addr, 0, NULL); | ||
| 159 | |||
| 160 | ps3_exit(); | ||
| 161 | } | ||
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index 7fd32330a9a5..eaa0d3ae3518 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c | |||
| @@ -27,7 +27,7 @@ static int serial_open(void) | |||
| 27 | return scdp->open(); | 27 | return scdp->open(); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static void serial_write(char *buf, int len) | 30 | static void serial_write(const char *buf, int len) |
| 31 | { | 31 | { |
| 32 | struct serial_console_data *scdp = console_ops.data; | 32 | struct serial_console_data *scdp = console_ops.data; |
| 33 | 33 | ||
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c index 0a9feeb98342..5b57800bbc67 100644 --- a/arch/powerpc/boot/stdio.c +++ b/arch/powerpc/boot/stdio.c | |||
| @@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args) | |||
| 190 | 190 | ||
| 191 | /* get the conversion qualifier */ | 191 | /* get the conversion qualifier */ |
| 192 | qualifier = -1; | 192 | qualifier = -1; |
| 193 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { | 193 | if (*fmt == 'l' && *(fmt + 1) == 'l') { |
| 194 | qualifier = 'q'; | ||
| 195 | fmt += 2; | ||
| 196 | } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' | ||
| 197 | || *fmt == 'Z') { | ||
| 194 | qualifier = *fmt; | 198 | qualifier = *fmt; |
| 195 | ++fmt; | 199 | ++fmt; |
| 196 | } | 200 | } |
| @@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args) | |||
| 281 | num = va_arg(args, unsigned long); | 285 | num = va_arg(args, unsigned long); |
| 282 | if (flags & SIGN) | 286 | if (flags & SIGN) |
| 283 | num = (signed long) num; | 287 | num = (signed long) num; |
| 288 | } else if (qualifier == 'q') { | ||
| 289 | num = va_arg(args, unsigned long long); | ||
| 290 | if (flags & SIGN) | ||
| 291 | num = (signed long long) num; | ||
| 284 | } else if (qualifier == 'Z') { | 292 | } else if (qualifier == 'Z') { |
| 285 | num = va_arg(args, size_t); | 293 | num = va_arg(args, size_t); |
| 286 | } else if (qualifier == 'h') { | 294 | } else if (qualifier == 'h') { |
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h index 79d26e708677..31393d17a9c1 100644 --- a/arch/powerpc/boot/types.h +++ b/arch/powerpc/boot/types.h | |||
| @@ -7,6 +7,10 @@ typedef unsigned char u8; | |||
| 7 | typedef unsigned short u16; | 7 | typedef unsigned short u16; |
| 8 | typedef unsigned int u32; | 8 | typedef unsigned int u32; |
| 9 | typedef unsigned long long u64; | 9 | typedef unsigned long long u64; |
| 10 | typedef signed char s8; | ||
| 11 | typedef short s16; | ||
| 12 | typedef int s32; | ||
| 13 | typedef long long s64; | ||
| 10 | 14 | ||
| 11 | #define min(x,y) ({ \ | 15 | #define min(x,y) ({ \ |
| 12 | typeof(x) _x = (x); \ | 16 | typeof(x) _x = (x); \ |
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index da77adc73078..65f685479175 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
| @@ -144,6 +144,15 @@ miboot|uboot) | |||
| 144 | cuboot*) | 144 | cuboot*) |
| 145 | gzip= | 145 | gzip= |
| 146 | ;; | 146 | ;; |
| 147 | ps3) | ||
| 148 | platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" | ||
| 149 | lds=$object/zImage.ps3.lds | ||
| 150 | gzip= | ||
| 151 | ext=bin | ||
| 152 | objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data" | ||
| 153 | ksection=.kernel:vmlinux.bin | ||
| 154 | isection=.kernel:initrd | ||
| 155 | ;; | ||
| 147 | esac | 156 | esac |
| 148 | 157 | ||
| 149 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" | 158 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" |
| @@ -239,4 +248,50 @@ treeboot*) | |||
| 239 | fi | 248 | fi |
| 240 | exit 0 | 249 | exit 0 |
| 241 | ;; | 250 | ;; |
| 251 | ps3) | ||
| 252 | # The ps3's loader supports loading gzipped binary images from flash | ||
| 253 | # rom to addr zero. The loader enters the image at addr 0x100. A | ||
| 254 | # bootwrapper overlay is use to arrange for the kernel to be loaded | ||
| 255 | # to addr zero and to have a suitable bootwrapper entry at 0x100. | ||
| 256 | # To construct the rom image, 0x100 bytes from offset 0x100 in the | ||
| 257 | # kernel is copied to the bootwrapper symbol __system_reset_kernel. | ||
| 258 | # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is | ||
| 259 | # then copied to offset 0x100. At runtime the bootwrapper program | ||
| 260 | # copies the 0x100 bytes at __system_reset_kernel to addr 0x100. | ||
| 261 | |||
| 262 | system_reset_overlay=0x`${CROSS}nm "$ofile" \ | ||
| 263 | | grep ' __system_reset_overlay$' \ | ||
| 264 | | cut -d' ' -f1` | ||
| 265 | system_reset_overlay=`printf "%d" $system_reset_overlay` | ||
| 266 | system_reset_kernel=0x`${CROSS}nm "$ofile" \ | ||
| 267 | | grep ' __system_reset_kernel$' \ | ||
| 268 | | cut -d' ' -f1` | ||
| 269 | system_reset_kernel=`printf "%d" $system_reset_kernel` | ||
| 270 | overlay_dest="256" | ||
| 271 | overlay_size="256" | ||
| 272 | |||
| 273 | rm -f "$object/otheros.bld" | ||
| 274 | |||
| 275 | ${CROSS}objcopy -O binary "$ofile" "$ofile.bin" | ||
| 276 | |||
| 277 | msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||
| 278 | skip=$overlay_dest seek=$system_reset_kernel \ | ||
| 279 | count=$overlay_size bs=1 2>&1) | ||
| 280 | |||
| 281 | if [ $? -ne "0" ]; then | ||
| 282 | echo $msg | ||
| 283 | exit 1 | ||
| 284 | fi | ||
| 285 | |||
| 286 | msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||
| 287 | skip=$system_reset_overlay seek=$overlay_dest \ | ||
| 288 | count=$overlay_size bs=1 2>&1) | ||
| 289 | |||
| 290 | if [ $? -ne "0" ]; then | ||
| 291 | echo $msg | ||
| 292 | exit 2 | ||
| 293 | fi | ||
| 294 | |||
| 295 | gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld" | ||
| 296 | ;; | ||
| 242 | esac | 297 | esac |
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S new file mode 100644 index 000000000000..aaa469c1e60d --- /dev/null +++ b/arch/powerpc/boot/zImage.ps3.lds.S | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | OUTPUT_ARCH(powerpc:common) | ||
| 2 | ENTRY(_zimage_start) | ||
| 3 | EXTERN(_zimage_start) | ||
| 4 | SECTIONS | ||
| 5 | { | ||
| 6 | _vmlinux_start = .; | ||
| 7 | .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) } | ||
| 8 | _vmlinux_end = .; | ||
| 9 | |||
| 10 | . = ALIGN(4096); | ||
| 11 | _dtb_start = .; | ||
| 12 | .kernel:dtb : { *(.kernel:dtb) } | ||
| 13 | _dtb_end = .; | ||
| 14 | |||
| 15 | . = ALIGN(4096); | ||
| 16 | _initrd_start = .; | ||
| 17 | .kernel:initrd : { *(.kernel:initrd) } | ||
| 18 | _initrd_end = .; | ||
| 19 | |||
| 20 | _start = .; | ||
| 21 | .text : | ||
| 22 | { | ||
| 23 | *(.text) | ||
| 24 | *(.fixup) | ||
| 25 | } | ||
| 26 | _etext = .; | ||
| 27 | . = ALIGN(4096); | ||
| 28 | .data : | ||
| 29 | { | ||
| 30 | *(.rodata*) | ||
| 31 | *(.data*) | ||
| 32 | *(.sdata*) | ||
| 33 | __got2_start = .; | ||
| 34 | *(.got2) | ||
| 35 | __got2_end = .; | ||
| 36 | } | ||
| 37 | |||
| 38 | . = ALIGN(4096); | ||
| 39 | _edata = .; | ||
| 40 | |||
| 41 | . = ALIGN(4096); | ||
| 42 | __bss_start = .; | ||
| 43 | .bss : | ||
| 44 | { | ||
| 45 | *(.sbss) | ||
| 46 | *(.bss) | ||
| 47 | } | ||
| 48 | . = ALIGN(4096); | ||
| 49 | _end = . ; | ||
| 50 | } | ||
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig index 32781849ad4c..04b94f884aae 100644 --- a/arch/powerpc/configs/holly_defconfig +++ b/arch/powerpc/configs/holly_defconfig | |||
| @@ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 | |||
| 190 | # CONFIG_RESOURCES_64BIT is not set | 190 | # CONFIG_RESOURCES_64BIT is not set |
| 191 | CONFIG_ZONE_DMA_FLAG=1 | 191 | CONFIG_ZONE_DMA_FLAG=1 |
| 192 | CONFIG_PROC_DEVICETREE=y | 192 | CONFIG_PROC_DEVICETREE=y |
| 193 | # CONFIG_CMDLINE_BOOL is not set | 193 | CONFIG_CMDLINE_BOOL=y |
| 194 | CONFIG_CMDLINE="console=ttyS0,115200" | ||
| 194 | # CONFIG_PM is not set | 195 | # CONFIG_PM is not set |
| 195 | # CONFIG_SECCOMP is not set | 196 | # CONFIG_SECCOMP is not set |
| 196 | # CONFIG_WANT_DEVICE_TREE is not set | 197 | CONFIG_WANT_DEVICE_TREE=y |
| 198 | CONFIG_DEVICE_TREE="holly.dts" | ||
| 197 | CONFIG_ISA_DMA_API=y | 199 | CONFIG_ISA_DMA_API=y |
| 198 | 200 | ||
| 199 | # | 201 | # |
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 956d1df61e0f..d0b43df44426 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig | |||
| @@ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20 | |||
| 156 | CONFIG_PS3_USE_LPAR_ADDR=y | 156 | CONFIG_PS3_USE_LPAR_ADDR=y |
| 157 | CONFIG_PS3_VUART=y | 157 | CONFIG_PS3_VUART=y |
| 158 | CONFIG_PS3_PS3AV=y | 158 | CONFIG_PS3_PS3AV=y |
| 159 | CONFIG_PS3_SYS_MANAGER=y | 159 | CONFIG_PS3_SYS_MANAGER=m |
| 160 | CONFIG_PS3_STORAGE=y | ||
| 161 | CONFIG_PS3_DISK=y | ||
| 162 | CONFIG_PS3_ROM=y | ||
| 163 | CONFIG_PS3_FLASH=y | ||
| 160 | CONFIG_PPC_CELL=y | 164 | CONFIG_PPC_CELL=y |
| 161 | # CONFIG_PPC_CELL_NATIVE is not set | 165 | # CONFIG_PPC_CELL_NATIVE is not set |
| 162 | # CONFIG_PPC_IBM_CELL_BLADE is not set | 166 | # CONFIG_PPC_IBM_CELL_BLADE is not set |
| @@ -335,7 +339,7 @@ CONFIG_BT=m | |||
| 335 | CONFIG_BT_L2CAP=m | 339 | CONFIG_BT_L2CAP=m |
| 336 | CONFIG_BT_SCO=m | 340 | CONFIG_BT_SCO=m |
| 337 | CONFIG_BT_RFCOMM=m | 341 | CONFIG_BT_RFCOMM=m |
| 338 | # CONFIG_BT_RFCOMM_TTY is not set | 342 | CONFIG_BT_RFCOMM_TTY=y |
| 339 | # CONFIG_BT_BNEP is not set | 343 | # CONFIG_BT_BNEP is not set |
| 340 | CONFIG_BT_HIDP=m | 344 | CONFIG_BT_HIDP=m |
| 341 | 345 | ||
| @@ -344,7 +348,9 @@ CONFIG_BT_HIDP=m | |||
| 344 | # | 348 | # |
| 345 | CONFIG_BT_HCIUSB=m | 349 | CONFIG_BT_HCIUSB=m |
| 346 | CONFIG_BT_HCIUSB_SCO=y | 350 | CONFIG_BT_HCIUSB_SCO=y |
| 347 | # CONFIG_BT_HCIUART is not set | 351 | CONFIG_BT_HCIUART=m |
| 352 | CONFIG_BT_HCIUART_H4=y | ||
| 353 | CONFIG_BT_HCIUART_BCSP=y | ||
| 348 | # CONFIG_BT_HCIBCM203X is not set | 354 | # CONFIG_BT_HCIBCM203X is not set |
| 349 | # CONFIG_BT_HCIBPA10X is not set | 355 | # CONFIG_BT_HCIBPA10X is not set |
| 350 | # CONFIG_BT_HCIBFUSB is not set | 356 | # CONFIG_BT_HCIBFUSB is not set |
| @@ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m | |||
| 435 | # | 441 | # |
| 436 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | 442 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs |
| 437 | # | 443 | # |
| 438 | # CONFIG_SCSI_MULTI_LUN is not set | 444 | CONFIG_SCSI_MULTI_LUN=y |
| 439 | # CONFIG_SCSI_CONSTANTS is not set | 445 | # CONFIG_SCSI_CONSTANTS is not set |
| 440 | # CONFIG_SCSI_LOGGING is not set | 446 | # CONFIG_SCSI_LOGGING is not set |
| 441 | # CONFIG_SCSI_SCAN_ASYNC is not set | 447 | # CONFIG_SCSI_SCAN_ASYNC is not set |
| @@ -479,6 +485,7 @@ CONFIG_NETDEVICES=y | |||
| 479 | CONFIG_MII=m | 485 | CONFIG_MII=m |
| 480 | CONFIG_NETDEV_1000=y | 486 | CONFIG_NETDEV_1000=y |
| 481 | CONFIG_NETDEV_10000=y | 487 | CONFIG_NETDEV_10000=y |
| 488 | CONFIG_GELIC_NET=y | ||
| 482 | 489 | ||
| 483 | # | 490 | # |
| 484 | # Wireless LAN | 491 | # Wireless LAN |
| @@ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | |||
| 546 | # | 553 | # |
| 547 | # CONFIG_INPUT_KEYBOARD is not set | 554 | # CONFIG_INPUT_KEYBOARD is not set |
| 548 | # CONFIG_INPUT_MOUSE is not set | 555 | # CONFIG_INPUT_MOUSE is not set |
| 549 | # CONFIG_INPUT_JOYSTICK is not set | 556 | CONFIG_INPUT_JOYSTICK=y |
| 557 | # CONFIG_JOYSTICK_ANALOG is not set | ||
| 558 | # CONFIG_JOYSTICK_A3D is not set | ||
| 559 | # CONFIG_JOYSTICK_ADI is not set | ||
| 560 | # CONFIG_JOYSTICK_COBRA is not set | ||
| 561 | # CONFIG_JOYSTICK_GF2K is not set | ||
| 562 | # CONFIG_JOYSTICK_GRIP is not set | ||
| 563 | # CONFIG_JOYSTICK_GRIP_MP is not set | ||
| 564 | # CONFIG_JOYSTICK_GUILLEMOT is not set | ||
| 565 | # CONFIG_JOYSTICK_INTERACT is not set | ||
| 566 | # CONFIG_JOYSTICK_SIDEWINDER is not set | ||
| 567 | # CONFIG_JOYSTICK_TMDC is not set | ||
| 568 | # CONFIG_JOYSTICK_IFORCE is not set | ||
| 569 | # CONFIG_JOYSTICK_WARRIOR is not set | ||
| 570 | # CONFIG_JOYSTICK_MAGELLAN is not set | ||
| 571 | # CONFIG_JOYSTICK_SPACEORB is not set | ||
| 572 | # CONFIG_JOYSTICK_SPACEBALL is not set | ||
| 573 | # CONFIG_JOYSTICK_STINGER is not set | ||
| 574 | # CONFIG_JOYSTICK_TWIDJOY is not set | ||
| 575 | # CONFIG_JOYSTICK_JOYDUMP is not set | ||
| 576 | # CONFIG_JOYSTICK_XPAD is not set | ||
| 550 | # CONFIG_INPUT_TABLET is not set | 577 | # CONFIG_INPUT_TABLET is not set |
| 551 | # CONFIG_INPUT_TOUCHSCREEN is not set | 578 | # CONFIG_INPUT_TOUCHSCREEN is not set |
| 552 | # CONFIG_INPUT_MISC is not set | 579 | # CONFIG_INPUT_MISC is not set |
| @@ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | |||
| 563 | CONFIG_VT=y | 590 | CONFIG_VT=y |
| 564 | CONFIG_VT_CONSOLE=y | 591 | CONFIG_VT_CONSOLE=y |
| 565 | CONFIG_HW_CONSOLE=y | 592 | CONFIG_HW_CONSOLE=y |
| 566 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | 593 | CONFIG_VT_HW_CONSOLE_BINDING=y |
| 567 | # CONFIG_SERIAL_NONSTANDARD is not set | 594 | # CONFIG_SERIAL_NONSTANDARD is not set |
| 568 | 595 | ||
| 569 | # | 596 | # |
| @@ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y | |||
| 1086 | # | 1113 | # |
| 1087 | # CONFIG_PRINTK_TIME is not set | 1114 | # CONFIG_PRINTK_TIME is not set |
| 1088 | CONFIG_ENABLE_MUST_CHECK=y | 1115 | CONFIG_ENABLE_MUST_CHECK=y |
| 1089 | # CONFIG_MAGIC_SYSRQ is not set | 1116 | CONFIG_MAGIC_SYSRQ=y |
| 1090 | # CONFIG_UNUSED_SYMBOLS is not set | 1117 | # CONFIG_UNUSED_SYMBOLS is not set |
| 1091 | # CONFIG_DEBUG_FS is not set | 1118 | # CONFIG_DEBUG_FS is not set |
| 1092 | # CONFIG_HEADERS_CHECK is not set | 1119 | # CONFIG_HEADERS_CHECK is not set |
| @@ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y | |||
| 1116 | # CONFIG_DEBUGGER is not set | 1143 | # CONFIG_DEBUGGER is not set |
| 1117 | CONFIG_IRQSTACKS=y | 1144 | CONFIG_IRQSTACKS=y |
| 1118 | # CONFIG_BOOTX_TEXT is not set | 1145 | # CONFIG_BOOTX_TEXT is not set |
| 1119 | CONFIG_PPC_EARLY_DEBUG=y | 1146 | # CONFIG_PPC_EARLY_DEBUG is not set |
| 1120 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
| 1121 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
| 1122 | # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||
| 1123 | # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||
| 1124 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
| 1125 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
| 1126 | # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set | ||
| 1127 | # CONFIG_PPC_EARLY_DEBUG_BEAT is not set | ||
| 1128 | # CONFIG_PPC_EARLY_DEBUG_44x is not set | ||
| 1129 | 1147 | ||
| 1130 | # | 1148 | # |
| 1131 | # Security options | 1149 | # Security options |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 3e779f07f21b..42c42ecad00c 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -12,7 +12,8 @@ endif | |||
| 12 | 12 | ||
| 13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
| 14 | irq.o align.o signal_32.o pmc.o vdso.o \ | 14 | irq.o align.o signal_32.o pmc.o vdso.o \ |
| 15 | init_task.o process.o systbl.o idle.o | 15 | init_task.o process.o systbl.o idle.o \ |
| 16 | signal.o | ||
| 16 | obj-y += vdso32/ | 17 | obj-y += vdso32/ |
| 17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 18 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
| 18 | signal_64.o ptrace32.o \ | 19 | signal_64.o ptrace32.o \ |
| @@ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o | |||
| 65 | module-$(CONFIG_PPC64) += module_64.o | 66 | module-$(CONFIG_PPC64) += module_64.o |
| 66 | obj-$(CONFIG_MODULES) += $(module-y) | 67 | obj-$(CONFIG_MODULES) += $(module-y) |
| 67 | 68 | ||
| 68 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o | 69 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o |
| 69 | pci32-$(CONFIG_PPC32) := pci_32.o | 70 | pci32-$(CONFIG_PPC32) := pci_32.o |
| 70 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 71 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o |
| 71 | obj-$(CONFIG_PCI_MSI) += msi.o | 72 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 72 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 73 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o |
| 73 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 74 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b2b5d664d328..b1f8000952f3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = { | |||
| 294 | .oprofile_mmcra_sipr = MMCRA_SIPR, | 294 | .oprofile_mmcra_sipr = MMCRA_SIPR, |
| 295 | .platform = "power5", | 295 | .platform = "power5", |
| 296 | }, | 296 | }, |
| 297 | { /* Power5++ */ | ||
| 298 | .pvr_mask = 0xffffff00, | ||
| 299 | .pvr_value = 0x003b0300, | ||
| 300 | .cpu_name = "POWER5+ (gs)", | ||
| 301 | .cpu_features = CPU_FTRS_POWER5, | ||
| 302 | .cpu_user_features = COMMON_USER_POWER5_PLUS, | ||
| 303 | .icache_bsize = 128, | ||
| 304 | .dcache_bsize = 128, | ||
| 305 | .num_pmcs = 6, | ||
| 306 | .oprofile_cpu_type = "ppc64/power5++", | ||
| 307 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
| 308 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
| 309 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
| 310 | .platform = "power5+", | ||
| 311 | }, | ||
| 297 | { /* Power5 GS */ | 312 | { /* Power5 GS */ |
| 298 | .pvr_mask = 0xffff0000, | 313 | .pvr_mask = 0xffff0000, |
| 299 | .pvr_value = 0x003b0000, | 314 | .pvr_value = 0x003b0000, |
| @@ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = { | |||
| 1178 | .platform = "ppc440", | 1193 | .platform = "ppc440", |
| 1179 | }, | 1194 | }, |
| 1180 | { /* 440SP Rev. A */ | 1195 | { /* 440SP Rev. A */ |
| 1181 | .pvr_mask = 0xff000fff, | 1196 | .pvr_mask = 0xfff00fff, |
| 1182 | .pvr_value = 0x53000891, | 1197 | .pvr_value = 0x53200891, |
| 1183 | .cpu_name = "440SP Rev. A", | 1198 | .cpu_name = "440SP Rev. A", |
| 1184 | .cpu_features = CPU_FTRS_44X, | 1199 | .cpu_features = CPU_FTRS_44X, |
| 1185 | .cpu_user_features = COMMON_USER_BOOKE, | 1200 | .cpu_user_features = COMMON_USER_BOOKE, |
| @@ -1188,9 +1203,19 @@ static struct cpu_spec cpu_specs[] = { | |||
| 1188 | .platform = "ppc440", | 1203 | .platform = "ppc440", |
| 1189 | }, | 1204 | }, |
| 1190 | { /* 440SPe Rev. A */ | 1205 | { /* 440SPe Rev. A */ |
| 1191 | .pvr_mask = 0xff000fff, | 1206 | .pvr_mask = 0xfff00fff, |
| 1192 | .pvr_value = 0x53000890, | 1207 | .pvr_value = 0x53400890, |
| 1193 | .cpu_name = "440SPe Rev. A", | 1208 | .cpu_name = "440SPe Rev. A", |
| 1209 | .cpu_features = CPU_FTRS_44X, | ||
| 1210 | .cpu_user_features = COMMON_USER_BOOKE, | ||
| 1211 | .icache_bsize = 32, | ||
| 1212 | .dcache_bsize = 32, | ||
| 1213 | .platform = "ppc440", | ||
| 1214 | }, | ||
| 1215 | { /* 440SPe Rev. B */ | ||
| 1216 | .pvr_mask = 0xfff00fff, | ||
| 1217 | .pvr_value = 0x53400891, | ||
| 1218 | .cpu_name = "440SPe Rev. B", | ||
| 1194 | .cpu_features = CPU_FTRS_44X, | 1219 | .cpu_features = CPU_FTRS_44X, |
| 1195 | .cpu_user_features = COMMON_USER_BOOKE, | 1220 | .cpu_user_features = COMMON_USER_BOOKE, |
| 1196 | .icache_bsize = 32, | 1221 | .icache_bsize = 32, |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index c897203198b1..7d73a13450b0 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * rewritten by Paul Mackerras. | 9 | * rewritten by Paul Mackerras. |
| 10 | * Copyright (C) 1996 Paul Mackerras. | 10 | * Copyright (C) 1996 Paul Mackerras. |
| 11 | * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). | 11 | * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). |
| 12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 13 | * | 12 | * |
| 14 | * This file contains the low-level support and setup for the | 13 | * This file contains the low-level support and setup for the |
| 15 | * PowerPC platform, including trap and interrupt dispatch. | 14 | * PowerPC platform, including trap and interrupt dispatch. |
| @@ -32,10 +31,6 @@ | |||
| 32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
| 33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
| 34 | 33 | ||
| 35 | #ifdef CONFIG_APUS | ||
| 36 | #include <asm/amigappc.h> | ||
| 37 | #endif | ||
| 38 | |||
| 39 | /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ | 34 | /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ |
| 40 | #define LOAD_BAT(n, reg, RA, RB) \ | 35 | #define LOAD_BAT(n, reg, RA, RB) \ |
| 41 | /* see the comment for clear_bats() -- Cort */ \ | 36 | /* see the comment for clear_bats() -- Cort */ \ |
| @@ -92,11 +87,6 @@ _start: | |||
| 92 | * r4: virtual address of boot_infos_t | 87 | * r4: virtual address of boot_infos_t |
| 93 | * r5: 0 | 88 | * r5: 0 |
| 94 | * | 89 | * |
| 95 | * APUS | ||
| 96 | * r3: 'APUS' | ||
| 97 | * r4: physical address of memory base | ||
| 98 | * Linux/m68k style BootInfo structure at &_end. | ||
| 99 | * | ||
| 100 | * PREP | 90 | * PREP |
| 101 | * This is jumped to on prep systems right after the kernel is relocated | 91 | * This is jumped to on prep systems right after the kernel is relocated |
| 102 | * to its proper place in memory by the boot loader. The expected layout | 92 | * to its proper place in memory by the boot loader. The expected layout |
| @@ -150,14 +140,6 @@ __start: | |||
| 150 | */ | 140 | */ |
| 151 | bl early_init | 141 | bl early_init |
| 152 | 142 | ||
| 153 | #ifdef CONFIG_APUS | ||
| 154 | /* On APUS the __va/__pa constants need to be set to the correct | ||
| 155 | * values before continuing. | ||
| 156 | */ | ||
| 157 | mr r4,r30 | ||
| 158 | bl fix_mem_constants | ||
| 159 | #endif /* CONFIG_APUS */ | ||
| 160 | |||
| 161 | /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains | 143 | /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains |
| 162 | * the physical address we are running at, returned by early_init() | 144 | * the physical address we are running at, returned by early_init() |
| 163 | */ | 145 | */ |
| @@ -167,7 +149,7 @@ __after_mmu_off: | |||
| 167 | bl flush_tlbs | 149 | bl flush_tlbs |
| 168 | 150 | ||
| 169 | bl initial_bats | 151 | bl initial_bats |
| 170 | #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | 152 | #if defined(CONFIG_BOOTX_TEXT) |
| 171 | bl setup_disp_bat | 153 | bl setup_disp_bat |
| 172 | #endif | 154 | #endif |
| 173 | 155 | ||
| @@ -183,7 +165,6 @@ __after_mmu_off: | |||
| 183 | #endif /* CONFIG_6xx */ | 165 | #endif /* CONFIG_6xx */ |
| 184 | 166 | ||
| 185 | 167 | ||
| 186 | #ifndef CONFIG_APUS | ||
| 187 | /* | 168 | /* |
| 188 | * We need to run with _start at physical address 0. | 169 | * We need to run with _start at physical address 0. |
| 189 | * On CHRP, we are loaded at 0x10000 since OF on CHRP uses | 170 | * On CHRP, we are loaded at 0x10000 since OF on CHRP uses |
| @@ -196,7 +177,6 @@ __after_mmu_off: | |||
| 196 | addis r4,r3,KERNELBASE@h /* current address of _start */ | 177 | addis r4,r3,KERNELBASE@h /* current address of _start */ |
| 197 | cmpwi 0,r4,0 /* are we already running at 0? */ | 178 | cmpwi 0,r4,0 /* are we already running at 0? */ |
| 198 | bne relocate_kernel | 179 | bne relocate_kernel |
| 199 | #endif /* CONFIG_APUS */ | ||
| 200 | /* | 180 | /* |
| 201 | * we now have the 1st 16M of ram mapped with the bats. | 181 | * we now have the 1st 16M of ram mapped with the bats. |
| 202 | * prep needs the mmu to be turned on here, but pmac already has it on. | 182 | * prep needs the mmu to be turned on here, but pmac already has it on. |
| @@ -881,85 +861,6 @@ _GLOBAL(copy_and_flush) | |||
| 881 | addi r6,r6,4 | 861 | addi r6,r6,4 |
| 882 | blr | 862 | blr |
| 883 | 863 | ||
| 884 | #ifdef CONFIG_APUS | ||
| 885 | /* | ||
| 886 | * On APUS the physical base address of the kernel is not known at compile | ||
| 887 | * time, which means the __pa/__va constants used are incorrect. In the | ||
| 888 | * __init section is recorded the virtual addresses of instructions using | ||
| 889 | * these constants, so all that has to be done is fix these before | ||
| 890 | * continuing the kernel boot. | ||
| 891 | * | ||
| 892 | * r4 = The physical address of the kernel base. | ||
| 893 | */ | ||
| 894 | fix_mem_constants: | ||
| 895 | mr r10,r4 | ||
| 896 | addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */ | ||
| 897 | neg r11,r10 /* phys_to_virt constant */ | ||
| 898 | |||
| 899 | lis r12,__vtop_table_begin@h | ||
| 900 | ori r12,r12,__vtop_table_begin@l | ||
| 901 | add r12,r12,r10 /* table begin phys address */ | ||
| 902 | lis r13,__vtop_table_end@h | ||
| 903 | ori r13,r13,__vtop_table_end@l | ||
| 904 | add r13,r13,r10 /* table end phys address */ | ||
| 905 | subi r12,r12,4 | ||
| 906 | subi r13,r13,4 | ||
| 907 | 1: lwzu r14,4(r12) /* virt address of instruction */ | ||
| 908 | add r14,r14,r10 /* phys address of instruction */ | ||
| 909 | lwz r15,0(r14) /* instruction, now insert top */ | ||
| 910 | rlwimi r15,r10,16,16,31 /* half of vp const in low half */ | ||
| 911 | stw r15,0(r14) /* of instruction and restore. */ | ||
| 912 | dcbst r0,r14 /* write it to memory */ | ||
| 913 | sync | ||
| 914 | icbi r0,r14 /* flush the icache line */ | ||
| 915 | cmpw r12,r13 | ||
| 916 | bne 1b | ||
| 917 | sync /* additional sync needed on g4 */ | ||
| 918 | isync | ||
| 919 | |||
| 920 | /* | ||
| 921 | * Map the memory where the exception handlers will | ||
| 922 | * be copied to when hash constants have been patched. | ||
| 923 | */ | ||
| 924 | #ifdef CONFIG_APUS_FAST_EXCEPT | ||
| 925 | lis r8,0xfff0 | ||
| 926 | #else | ||
| 927 | lis r8,0 | ||
| 928 | #endif | ||
| 929 | ori r8,r8,0x2 /* 128KB, supervisor */ | ||
| 930 | mtspr SPRN_DBAT3U,r8 | ||
| 931 | mtspr SPRN_DBAT3L,r8 | ||
| 932 | |||
| 933 | lis r12,__ptov_table_begin@h | ||
| 934 | ori r12,r12,__ptov_table_begin@l | ||
| 935 | add r12,r12,r10 /* table begin phys address */ | ||
| 936 | lis r13,__ptov_table_end@h | ||
| 937 | ori r13,r13,__ptov_table_end@l | ||
| 938 | add r13,r13,r10 /* table end phys address */ | ||
| 939 | subi r12,r12,4 | ||
| 940 | subi r13,r13,4 | ||
| 941 | 1: lwzu r14,4(r12) /* virt address of instruction */ | ||
| 942 | add r14,r14,r10 /* phys address of instruction */ | ||
| 943 | lwz r15,0(r14) /* instruction, now insert top */ | ||
| 944 | rlwimi r15,r11,16,16,31 /* half of pv const in low half*/ | ||
| 945 | stw r15,0(r14) /* of instruction and restore. */ | ||
| 946 | dcbst r0,r14 /* write it to memory */ | ||
| 947 | sync | ||
| 948 | icbi r0,r14 /* flush the icache line */ | ||
| 949 | cmpw r12,r13 | ||
| 950 | bne 1b | ||
| 951 | |||
| 952 | sync /* additional sync needed on g4 */ | ||
| 953 | isync /* No speculative loading until now */ | ||
| 954 | blr | ||
| 955 | |||
| 956 | /*********************************************************************** | ||
| 957 | * Please note that on APUS the exception handlers are located at the | ||
| 958 | * physical address 0xfff0000. For this reason, the exception handlers | ||
| 959 | * cannot use relative branches to access the code below. | ||
| 960 | ***********************************************************************/ | ||
| 961 | #endif /* CONFIG_APUS */ | ||
| 962 | |||
| 963 | #ifdef CONFIG_SMP | 864 | #ifdef CONFIG_SMP |
| 964 | #ifdef CONFIG_GEMINI | 865 | #ifdef CONFIG_GEMINI |
| 965 | .globl __secondary_start_gemini | 866 | .globl __secondary_start_gemini |
| @@ -1135,19 +1036,6 @@ start_here: | |||
| 1135 | bl __save_cpu_setup | 1036 | bl __save_cpu_setup |
| 1136 | bl MMU_init | 1037 | bl MMU_init |
| 1137 | 1038 | ||
| 1138 | #ifdef CONFIG_APUS | ||
| 1139 | /* Copy exception code to exception vector base on APUS. */ | ||
| 1140 | lis r4,KERNELBASE@h | ||
| 1141 | #ifdef CONFIG_APUS_FAST_EXCEPT | ||
| 1142 | lis r3,0xfff0 /* Copy to 0xfff00000 */ | ||
| 1143 | #else | ||
| 1144 | lis r3,0 /* Copy to 0x00000000 */ | ||
| 1145 | #endif | ||
| 1146 | li r5,0x4000 /* # bytes of memory to copy */ | ||
| 1147 | li r6,0 | ||
| 1148 | bl copy_and_flush /* copy the first 0x4000 bytes */ | ||
| 1149 | #endif /* CONFIG_APUS */ | ||
| 1150 | |||
| 1151 | /* | 1039 | /* |
| 1152 | * Go back to running unmapped so we can load up new values | 1040 | * Go back to running unmapped so we can load up new values |
| 1153 | * for SDR1 (hash table pointer) and the segment registers | 1041 | * for SDR1 (hash table pointer) and the segment registers |
| @@ -1324,11 +1212,7 @@ initial_bats: | |||
| 1324 | #else | 1212 | #else |
| 1325 | ori r8,r8,2 /* R/W access */ | 1213 | ori r8,r8,2 /* R/W access */ |
| 1326 | #endif /* CONFIG_SMP */ | 1214 | #endif /* CONFIG_SMP */ |
| 1327 | #ifdef CONFIG_APUS | ||
| 1328 | ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ | ||
| 1329 | #else | ||
| 1330 | ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ | 1215 | ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ |
| 1331 | #endif /* CONFIG_APUS */ | ||
| 1332 | 1216 | ||
| 1333 | mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ | 1217 | mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ |
| 1334 | mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ | 1218 | mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ |
| @@ -1338,7 +1222,7 @@ initial_bats: | |||
| 1338 | blr | 1222 | blr |
| 1339 | 1223 | ||
| 1340 | 1224 | ||
| 1341 | #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | 1225 | #ifdef CONFIG_BOOTX_TEXT |
| 1342 | setup_disp_bat: | 1226 | setup_disp_bat: |
| 1343 | /* | 1227 | /* |
| 1344 | * setup the display bat prepared for us in prom.c | 1228 | * setup the display bat prepared for us in prom.c |
| @@ -1362,7 +1246,7 @@ setup_disp_bat: | |||
| 1362 | 1: mtspr SPRN_IBAT3L,r8 | 1246 | 1: mtspr SPRN_IBAT3L,r8 |
| 1363 | mtspr SPRN_IBAT3U,r11 | 1247 | mtspr SPRN_IBAT3U,r11 |
| 1364 | blr | 1248 | blr |
| 1365 | #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ | 1249 | #endif /* CONFIG_BOOTX_TEXT */ |
| 1366 | 1250 | ||
| 1367 | #ifdef CONFIG_8260 | 1251 | #ifdef CONFIG_8260 |
| 1368 | /* Jump into the system reset for the rom. | 1252 | /* Jump into the system reset for the rom. |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1111fcec7673..8cdd48ea4391 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -103,8 +103,8 @@ __secondary_hold_acknowledge: | |||
| 103 | 103 | ||
| 104 | . = 0x60 | 104 | . = 0x60 |
| 105 | /* | 105 | /* |
| 106 | * The following code is used on pSeries to hold secondary processors | 106 | * The following code is used to hold secondary processors |
| 107 | * in a spin loop after they have been freed from OpenFirmware, but | 107 | * in a spin loop after they have entered the kernel, but |
| 108 | * before the bulk of the kernel has been relocated. This code | 108 | * before the bulk of the kernel has been relocated. This code |
| 109 | * is relocated to physical address 0x60 before prom_init is run. | 109 | * is relocated to physical address 0x60 before prom_init is run. |
| 110 | * All of it must fit below the first exception vector at 0x100. | 110 | * All of it must fit below the first exception vector at 0x100. |
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 34ae11494ddc..e31aca9208eb 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c | |||
| @@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count) | |||
| 35 | asm volatile("sync"); | 35 | asm volatile("sync"); |
| 36 | do { | 36 | do { |
| 37 | tmp = *port; | 37 | tmp = *port; |
| 38 | asm volatile("eieio"); | 38 | eieio(); |
| 39 | *tbuf++ = tmp; | 39 | *tbuf++ = tmp; |
| 40 | } while (--count != 0); | 40 | } while (--count != 0); |
| 41 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 41 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
| @@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) | |||
| 66 | asm volatile("sync"); | 66 | asm volatile("sync"); |
| 67 | do { | 67 | do { |
| 68 | tmp = *port; | 68 | tmp = *port; |
| 69 | asm volatile("eieio"); | 69 | eieio(); |
| 70 | *tbuf++ = tmp; | 70 | *tbuf++ = tmp; |
| 71 | } while (--count != 0); | 71 | } while (--count != 0); |
| 72 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 72 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
| @@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) | |||
| 97 | asm volatile("sync"); | 97 | asm volatile("sync"); |
| 98 | do { | 98 | do { |
| 99 | tmp = *port; | 99 | tmp = *port; |
| 100 | asm volatile("eieio"); | 100 | eieio(); |
| 101 | *tbuf++ = tmp; | 101 | *tbuf++ = tmp; |
| 102 | } while (--count != 0); | 102 | } while (--count != 0); |
| 103 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 103 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
| @@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, | |||
| 155 | __asm__ __volatile__ ("sync" : : : "memory"); | 155 | __asm__ __volatile__ ("sync" : : : "memory"); |
| 156 | while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { | 156 | while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { |
| 157 | *((u8 *)dest) = *((volatile u8 *)vsrc); | 157 | *((u8 *)dest) = *((volatile u8 *)vsrc); |
| 158 | __asm__ __volatile__ ("eieio" : : : "memory"); | 158 | eieio(); |
| 159 | vsrc++; | 159 | vsrc++; |
| 160 | dest++; | 160 | dest++; |
| 161 | n--; | 161 | n--; |
| 162 | } | 162 | } |
| 163 | while(n > 4) { | 163 | while(n > 4) { |
| 164 | *((u32 *)dest) = *((volatile u32 *)vsrc); | 164 | *((u32 *)dest) = *((volatile u32 *)vsrc); |
| 165 | __asm__ __volatile__ ("eieio" : : : "memory"); | 165 | eieio(); |
| 166 | vsrc += 4; | 166 | vsrc += 4; |
| 167 | dest += 4; | 167 | dest += 4; |
| 168 | n -= 4; | 168 | n -= 4; |
| 169 | } | 169 | } |
| 170 | while(n) { | 170 | while(n) { |
| 171 | *((u8 *)dest) = *((volatile u8 *)vsrc); | 171 | *((u8 *)dest) = *((volatile u8 *)vsrc); |
| 172 | __asm__ __volatile__ ("eieio" : : : "memory"); | 172 | eieio(); |
| 173 | vsrc++; | 173 | vsrc++; |
| 174 | dest++; | 174 | dest++; |
| 175 | n--; | 175 | n--; |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c2b84c64db20..2fc87862146c 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * Copyright (C) 1996-2001 Cort Dougan | 7 | * Copyright (C) 1996-2001 Cort Dougan |
| 8 | * Adapted for Power Macintosh by Paul Mackerras | 8 | * Adapted for Power Macintosh by Paul Mackerras |
| 9 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | 9 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) |
| 10 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 11 | * | 10 | * |
| 12 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
| @@ -337,7 +336,8 @@ void do_IRQ(struct pt_regs *regs) | |||
| 337 | 336 | ||
| 338 | void __init init_IRQ(void) | 337 | void __init init_IRQ(void) |
| 339 | { | 338 | { |
| 340 | ppc_md.init_IRQ(); | 339 | if (ppc_md.init_IRQ) |
| 340 | ppc_md.init_IRQ(); | ||
| 341 | #ifdef CONFIG_PPC64 | 341 | #ifdef CONFIG_PPC64 |
| 342 | irq_ctx_init(); | 342 | irq_ctx_init(); |
| 343 | #endif | 343 | #endif |
| @@ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags) | |||
| 597 | local_irq_restore(flags); | 597 | local_irq_restore(flags); |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, | ||
| 601 | irq_hw_number_t hwirq) | ||
| 602 | { | ||
| 603 | /* Clear IRQ_NOREQUEST flag */ | ||
| 604 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||
| 605 | |||
| 606 | /* map it */ | ||
| 607 | smp_wmb(); | ||
| 608 | irq_map[virq].hwirq = hwirq; | ||
| 609 | smp_mb(); | ||
| 610 | |||
| 611 | if (host->ops->map(host, virq, hwirq)) { | ||
| 612 | pr_debug("irq: -> mapping failed, freeing\n"); | ||
| 613 | irq_free_virt(virq, 1); | ||
| 614 | return -1; | ||
| 615 | } | ||
| 616 | |||
| 617 | return 0; | ||
| 618 | } | ||
| 619 | |||
| 620 | unsigned int irq_create_direct_mapping(struct irq_host *host) | ||
| 621 | { | ||
| 622 | unsigned int virq; | ||
| 623 | |||
| 624 | if (host == NULL) | ||
| 625 | host = irq_default_host; | ||
| 626 | |||
| 627 | BUG_ON(host == NULL); | ||
| 628 | WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); | ||
| 629 | |||
| 630 | virq = irq_alloc_virt(host, 1, 0); | ||
| 631 | if (virq == NO_IRQ) { | ||
| 632 | pr_debug("irq: create_direct virq allocation failed\n"); | ||
| 633 | return NO_IRQ; | ||
| 634 | } | ||
| 635 | |||
| 636 | pr_debug("irq: create_direct obtained virq %d\n", virq); | ||
| 637 | |||
| 638 | if (irq_setup_virq(host, virq, virq)) | ||
| 639 | return NO_IRQ; | ||
| 640 | |||
| 641 | return virq; | ||
| 642 | } | ||
| 600 | 643 | ||
| 601 | unsigned int irq_create_mapping(struct irq_host *host, | 644 | unsigned int irq_create_mapping(struct irq_host *host, |
| 602 | irq_hw_number_t hwirq) | 645 | irq_hw_number_t hwirq) |
| @@ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
| 645 | } | 688 | } |
| 646 | pr_debug("irq: -> obtained virq %d\n", virq); | 689 | pr_debug("irq: -> obtained virq %d\n", virq); |
| 647 | 690 | ||
| 648 | /* Clear IRQ_NOREQUEST flag */ | 691 | if (irq_setup_virq(host, virq, hwirq)) |
| 649 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||
| 650 | |||
| 651 | /* map it */ | ||
| 652 | smp_wmb(); | ||
| 653 | irq_map[virq].hwirq = hwirq; | ||
| 654 | smp_mb(); | ||
| 655 | if (host->ops->map(host, virq, hwirq)) { | ||
| 656 | pr_debug("irq: -> mapping failed, freeing\n"); | ||
| 657 | irq_free_virt(virq, 1); | ||
| 658 | return NO_IRQ; | 692 | return NO_IRQ; |
| 659 | } | 693 | |
| 660 | return virq; | 694 | return virq; |
| 661 | } | 695 | } |
| 662 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 696 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c new file mode 100644 index 000000000000..f0f49d1be3d5 --- /dev/null +++ b/arch/powerpc/kernel/isa-bridge.c | |||
| @@ -0,0 +1,271 @@ | |||
| 1 | /* | ||
| 2 | * Routines for tracking a legacy ISA bridge | ||
| 3 | * | ||
| 4 | * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | ||
| 5 | * | ||
| 6 | * Some bits and pieces moved over from pci_64.c | ||
| 7 | * | ||
| 8 | * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #define DEBUG | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/pci.h> | ||
| 20 | #include <linux/string.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/notifier.h> | ||
| 24 | |||
| 25 | #include <asm/processor.h> | ||
| 26 | #include <asm/io.h> | ||
| 27 | #include <asm/prom.h> | ||
| 28 | #include <asm/pci-bridge.h> | ||
| 29 | #include <asm/machdep.h> | ||
| 30 | #include <asm/ppc-pci.h> | ||
| 31 | #include <asm/firmware.h> | ||
| 32 | |||
| 33 | unsigned long isa_io_base; /* NULL if no ISA bus */ | ||
| 34 | EXPORT_SYMBOL(isa_io_base); | ||
| 35 | |||
| 36 | /* Cached ISA bridge dev. */ | ||
| 37 | static struct device_node *isa_bridge_devnode; | ||
| 38 | struct pci_dev *isa_bridge_pcidev; | ||
| 39 | EXPORT_SYMBOL_GPL(isa_bridge_pcidev); | ||
| 40 | |||
| 41 | #define ISA_SPACE_MASK 0x1 | ||
| 42 | #define ISA_SPACE_IO 0x1 | ||
| 43 | |||
| 44 | static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||
| 45 | unsigned long phb_io_base_phys) | ||
| 46 | { | ||
| 47 | /* We should get some saner parsing here and remove these structs */ | ||
| 48 | struct pci_address { | ||
| 49 | u32 a_hi; | ||
| 50 | u32 a_mid; | ||
| 51 | u32 a_lo; | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct isa_address { | ||
| 55 | u32 a_hi; | ||
| 56 | u32 a_lo; | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct isa_range { | ||
| 60 | struct isa_address isa_addr; | ||
| 61 | struct pci_address pci_addr; | ||
| 62 | unsigned int size; | ||
| 63 | }; | ||
| 64 | |||
| 65 | const struct isa_range *range; | ||
| 66 | unsigned long pci_addr; | ||
| 67 | unsigned int isa_addr; | ||
| 68 | unsigned int size; | ||
| 69 | int rlen = 0; | ||
| 70 | |||
| 71 | range = of_get_property(isa_node, "ranges", &rlen); | ||
| 72 | if (range == NULL || (rlen < sizeof(struct isa_range))) | ||
| 73 | goto inval_range; | ||
| 74 | |||
| 75 | /* From "ISA Binding to 1275" | ||
| 76 | * The ranges property is laid out as an array of elements, | ||
| 77 | * each of which comprises: | ||
| 78 | * cells 0 - 1: an ISA address | ||
| 79 | * cells 2 - 4: a PCI address | ||
| 80 | * (size depending on dev->n_addr_cells) | ||
| 81 | * cell 5: the size of the range | ||
| 82 | */ | ||
| 83 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) { | ||
| 84 | range++; | ||
| 85 | rlen -= sizeof(struct isa_range); | ||
| 86 | if (rlen < sizeof(struct isa_range)) | ||
| 87 | goto inval_range; | ||
| 88 | } | ||
| 89 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) | ||
| 90 | goto inval_range; | ||
| 91 | |||
| 92 | isa_addr = range->isa_addr.a_lo; | ||
| 93 | pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | | ||
| 94 | range->pci_addr.a_lo; | ||
| 95 | |||
| 96 | /* Assume these are both zero. Note: We could fix that and | ||
| 97 | * do a proper parsing instead ... oh well, that will do for | ||
| 98 | * now as nobody uses fancy mappings for ISA bridges | ||
| 99 | */ | ||
| 100 | if ((pci_addr != 0) || (isa_addr != 0)) { | ||
| 101 | printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||
| 102 | __FUNCTION__); | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* Align size and make sure it's cropped to 64K */ | ||
| 107 | size = PAGE_ALIGN(range->size); | ||
| 108 | if (size > 0x10000) | ||
| 109 | size = 0x10000; | ||
| 110 | |||
| 111 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||
| 112 | "mapping 64k\n"); | ||
| 113 | |||
| 114 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||
| 115 | size, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||
| 116 | return; | ||
| 117 | |||
| 118 | inval_range: | ||
| 119 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||
| 120 | "mapping 64k\n"); | ||
| 121 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||
| 122 | 0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | /** | ||
| 127 | * isa_bridge_find_early - Find and map the ISA IO space early before | ||
| 128 | * main PCI discovery. This is optionally called by | ||
| 129 | * the arch code when adding PCI PHBs to get early | ||
| 130 | * access to ISA IO ports | ||
| 131 | */ | ||
| 132 | void __init isa_bridge_find_early(struct pci_controller *hose) | ||
| 133 | { | ||
| 134 | struct device_node *np, *parent = NULL, *tmp; | ||
| 135 | |||
| 136 | /* If we already have an ISA bridge, bail off */ | ||
| 137 | if (isa_bridge_devnode != NULL) | ||
| 138 | return; | ||
| 139 | |||
| 140 | /* For each "isa" node in the system. Note : we do a search by | ||
| 141 | * type and not by name. It might be better to do by name but that's | ||
| 142 | * what the code used to do and I don't want to break too much at | ||
| 143 | * once. We can look into changing that separately | ||
| 144 | */ | ||
| 145 | for_each_node_by_type(np, "isa") { | ||
| 146 | /* Look for our hose being a parent */ | ||
| 147 | for (parent = of_get_parent(np); parent;) { | ||
| 148 | if (parent == hose->arch_data) { | ||
| 149 | of_node_put(parent); | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | tmp = parent; | ||
| 153 | parent = of_get_parent(parent); | ||
| 154 | of_node_put(tmp); | ||
| 155 | } | ||
| 156 | if (parent != NULL) | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | if (np == NULL) | ||
| 160 | return; | ||
| 161 | isa_bridge_devnode = np; | ||
| 162 | |||
| 163 | /* Now parse the "ranges" property and setup the ISA mapping */ | ||
| 164 | pci_process_ISA_OF_ranges(np, hose->io_base_phys); | ||
| 165 | |||
| 166 | /* Set the global ISA io base to indicate we have an ISA bridge */ | ||
| 167 | isa_io_base = ISA_IO_BASE; | ||
| 168 | |||
| 169 | pr_debug("ISA bridge (early) is %s\n", np->full_name); | ||
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * isa_bridge_find_late - Find and map the ISA IO space upon discovery of | ||
| 174 | * a new ISA bridge | ||
| 175 | */ | ||
| 176 | static void __devinit isa_bridge_find_late(struct pci_dev *pdev, | ||
| 177 | struct device_node *devnode) | ||
| 178 | { | ||
| 179 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
| 180 | |||
| 181 | /* Store ISA device node and PCI device */ | ||
| 182 | isa_bridge_devnode = of_node_get(devnode); | ||
| 183 | isa_bridge_pcidev = pdev; | ||
| 184 | |||
| 185 | /* Now parse the "ranges" property and setup the ISA mapping */ | ||
| 186 | pci_process_ISA_OF_ranges(devnode, hose->io_base_phys); | ||
| 187 | |||
| 188 | /* Set the global ISA io base to indicate we have an ISA bridge */ | ||
| 189 | isa_io_base = ISA_IO_BASE; | ||
| 190 | |||
| 191 | pr_debug("ISA bridge (late) is %s on %s\n", | ||
| 192 | devnode->full_name, pci_name(pdev)); | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * isa_bridge_remove - Remove/unmap an ISA bridge | ||
| 197 | */ | ||
| 198 | static void isa_bridge_remove(void) | ||
| 199 | { | ||
| 200 | pr_debug("ISA bridge removed !\n"); | ||
| 201 | |||
| 202 | /* Clear the global ISA io base to indicate that we have no more | ||
| 203 | * ISA bridge. Note that drivers don't quite handle that, though | ||
| 204 | * we should probably do something about it. But do we ever really | ||
| 205 | * have ISA bridges being removed on machines using legacy devices ? | ||
| 206 | */ | ||
| 207 | isa_io_base = ISA_IO_BASE; | ||
| 208 | |||
| 209 | /* Clear references to the bridge */ | ||
| 210 | of_node_put(isa_bridge_devnode); | ||
| 211 | isa_bridge_devnode = NULL; | ||
| 212 | isa_bridge_pcidev = NULL; | ||
| 213 | |||
| 214 | /* Unmap the ISA area */ | ||
| 215 | __iounmap_at((void *)ISA_IO_BASE, 0x10000); | ||
| 216 | } | ||
| 217 | |||
| 218 | /** | ||
| 219 | * isa_bridge_notify - Get notified of PCI devices addition/removal | ||
| 220 | */ | ||
| 221 | static int __devinit isa_bridge_notify(struct notifier_block *nb, | ||
| 222 | unsigned long action, void *data) | ||
| 223 | { | ||
| 224 | struct device *dev = data; | ||
| 225 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 226 | struct device_node *devnode = pci_device_to_OF_node(pdev); | ||
| 227 | |||
| 228 | switch(action) { | ||
| 229 | case BUS_NOTIFY_ADD_DEVICE: | ||
| 230 | /* Check if we have an early ISA device, without PCI dev */ | ||
| 231 | if (isa_bridge_devnode && isa_bridge_devnode == devnode && | ||
| 232 | !isa_bridge_pcidev) { | ||
| 233 | pr_debug("ISA bridge PCI attached: %s\n", | ||
| 234 | pci_name(pdev)); | ||
| 235 | isa_bridge_pcidev = pdev; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* Check if we have no ISA device, and this happens to be one, | ||
| 239 | * register it as such if it has an OF device | ||
| 240 | */ | ||
| 241 | if (!isa_bridge_devnode && devnode && devnode->type && | ||
| 242 | !strcmp(devnode->type, "isa")) | ||
| 243 | isa_bridge_find_late(pdev, devnode); | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | case BUS_NOTIFY_DEL_DEVICE: | ||
| 247 | /* Check if this our existing ISA device */ | ||
| 248 | if (pdev == isa_bridge_pcidev || | ||
| 249 | (devnode && devnode == isa_bridge_devnode)) | ||
| 250 | isa_bridge_remove(); | ||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static struct notifier_block isa_bridge_notifier = { | ||
| 257 | .notifier_call = isa_bridge_notify | ||
| 258 | }; | ||
| 259 | |||
| 260 | /** | ||
| 261 | * isa_bridge_init - register to be notified of ISA bridge addition/removal | ||
| 262 | * | ||
| 263 | */ | ||
| 264 | static int __init isa_bridge_init(void) | ||
| 265 | { | ||
| 266 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 267 | return 0; | ||
| 268 | bus_register_notifier(&pci_bus_type, &isa_bridge_notifier); | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | arch_initcall(isa_bridge_init); | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 98decf8ebff4..e708ab7ca9e8 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -392,7 +392,7 @@ BEGIN_FTR_SECTION | |||
| 392 | mtspr SPRN_L1CSR0,r3 | 392 | mtspr SPRN_L1CSR0,r3 |
| 393 | isync | 393 | isync |
| 394 | blr | 394 | blr |
| 395 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 395 | END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) |
| 396 | mfspr r3,SPRN_L1CSR1 | 396 | mfspr r3,SPRN_L1CSR1 |
| 397 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | 397 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR |
| 398 | mtspr SPRN_L1CSR1,r3 | 398 | mtspr SPRN_L1CSR1,r3 |
| @@ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
| 419 | _GLOBAL(__flush_icache_range) | 419 | _GLOBAL(__flush_icache_range) |
| 420 | BEGIN_FTR_SECTION | 420 | BEGIN_FTR_SECTION |
| 421 | blr /* for 601, do nothing */ | 421 | blr /* for 601, do nothing */ |
| 422 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 422 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 423 | li r5,L1_CACHE_BYTES-1 | 423 | li r5,L1_CACHE_BYTES-1 |
| 424 | andc r3,r3,r5 | 424 | andc r3,r3,r5 |
| 425 | subf r4,r3,r4 | 425 | subf r4,r3,r4 |
| @@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range) | |||
| 514 | */ | 514 | */ |
| 515 | _GLOBAL(__flush_dcache_icache) | 515 | _GLOBAL(__flush_dcache_icache) |
| 516 | BEGIN_FTR_SECTION | 516 | BEGIN_FTR_SECTION |
| 517 | blr /* for 601, do nothing */ | 517 | blr |
| 518 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 518 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 519 | rlwinm r3,r3,0,0,19 /* Get page base address */ | 519 | rlwinm r3,r3,0,0,19 /* Get page base address */ |
| 520 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ | 520 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ |
| 521 | mtctr r4 | 521 | mtctr r4 |
| @@ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
| 543 | _GLOBAL(__flush_dcache_icache_phys) | 543 | _GLOBAL(__flush_dcache_icache_phys) |
| 544 | BEGIN_FTR_SECTION | 544 | BEGIN_FTR_SECTION |
| 545 | blr /* for 601, do nothing */ | 545 | blr /* for 601, do nothing */ |
| 546 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 546 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 547 | mfmsr r10 | 547 | mfmsr r10 |
| 548 | rlwinm r0,r10,0,28,26 /* clear DR */ | 548 | rlwinm r0,r10,0,28,26 /* clear DR */ |
| 549 | mtmsr r0 | 549 | mtmsr r0 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 519861da0423..bbb3ba54c51c 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
| @@ -646,6 +646,19 @@ _GLOBAL(kexec_sequence) | |||
| 646 | /* turn off mmu */ | 646 | /* turn off mmu */ |
| 647 | bl real_mode | 647 | bl real_mode |
| 648 | 648 | ||
| 649 | /* copy 0x100 bytes starting at start to 0 */ | ||
| 650 | li r3,0 | ||
| 651 | mr r4,r30 /* start, aka phys mem offset */ | ||
| 652 | li r5,0x100 | ||
| 653 | li r6,0 | ||
| 654 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
| 655 | 1: /* assume normal blr return */ | ||
| 656 | |||
| 657 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
| 658 | mflr r5 | ||
| 659 | li r6,1 | ||
| 660 | stw r6,kexec_flag-1b(5) | ||
| 661 | |||
| 649 | /* clear out hardware hash page table and tlb */ | 662 | /* clear out hardware hash page table and tlb */ |
| 650 | ld r5,0(r27) /* deref function descriptor */ | 663 | ld r5,0(r27) /* deref function descriptor */ |
| 651 | mtctr r5 | 664 | mtctr r5 |
| @@ -676,19 +689,6 @@ _GLOBAL(kexec_sequence) | |||
| 676 | * are the boot cpu ????? | 689 | * are the boot cpu ????? |
| 677 | * other device tree differences (prop sizes, va vs pa, etc)... | 690 | * other device tree differences (prop sizes, va vs pa, etc)... |
| 678 | */ | 691 | */ |
| 679 | |||
| 680 | /* copy 0x100 bytes starting at start to 0 */ | ||
| 681 | li r3,0 | ||
| 682 | mr r4,r30 | ||
| 683 | li r5,0x100 | ||
| 684 | li r6,0 | ||
| 685 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
| 686 | 1: /* assume normal blr return */ | ||
| 687 | |||
| 688 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
| 689 | mflr r5 | ||
| 690 | li r6,1 | ||
| 691 | stw r6,kexec_flag-1b(5) | ||
| 692 | mr r3,r25 # my phys cpu | 692 | mr r3,r25 # my phys cpu |
| 693 | mr r4,r30 # start, aka phys mem offset | 693 | mr r4,r30 # start, aka phys mem offset |
| 694 | mtlr 4 | 694 | mtlr 4 |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index d454f61c9c7c..9536ed7f247c 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
| @@ -427,14 +427,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, | |||
| 427 | /* Process "ranges" property */ | 427 | /* Process "ranges" property */ |
| 428 | pci_process_bridge_OF_ranges(phb, dev->node, 0); | 428 | pci_process_bridge_OF_ranges(phb, dev->node, 0); |
| 429 | 429 | ||
| 430 | /* Setup IO space. We use the non-dynamic version of that code here, | ||
| 431 | * which doesn't quite support unplugging. Next kernel release will | ||
| 432 | * have a better fix for this. | ||
| 433 | * Note also that we don't do ISA, this will also be fixed with a | ||
| 434 | * more massive rework. | ||
| 435 | */ | ||
| 436 | pci_setup_phb_io(phb, pci_io_base == 0); | ||
| 437 | |||
| 438 | /* Init pci_dn data structures */ | 430 | /* Init pci_dn data structures */ |
| 439 | pci_devs_phb_init_dynamic(phb); | 431 | pci_devs_phb_init_dynamic(phb); |
| 440 | 432 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c new file mode 100644 index 000000000000..faf5ef3e90d0 --- /dev/null +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -0,0 +1,454 @@ | |||
| 1 | /* | ||
| 2 | * Contains common pci routines for ALL ppc platform | ||
| 3 | * (based on pci_32.c and pci_64.c) | ||
| 4 | * | ||
| 5 | * Port for PPC64 David Engebretsen, IBM Corp. | ||
| 6 | * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. | ||
| 7 | * | ||
| 8 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | ||
| 9 | * Rework, based on alpha PCI code. | ||
| 10 | * | ||
| 11 | * Common pmac/prep/chrp pci routines. -- Cort | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License | ||
| 15 | * as published by the Free Software Foundation; either version | ||
| 16 | * 2 of the License, or (at your option) any later version. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #undef DEBUG | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/pci.h> | ||
| 23 | #include <linux/string.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/bootmem.h> | ||
| 26 | #include <linux/mm.h> | ||
| 27 | #include <linux/list.h> | ||
| 28 | #include <linux/syscalls.h> | ||
| 29 | #include <linux/irq.h> | ||
| 30 | #include <linux/vmalloc.h> | ||
| 31 | |||
| 32 | #include <asm/processor.h> | ||
| 33 | #include <asm/io.h> | ||
| 34 | #include <asm/prom.h> | ||
| 35 | #include <asm/pci-bridge.h> | ||
| 36 | #include <asm/byteorder.h> | ||
| 37 | #include <asm/machdep.h> | ||
| 38 | #include <asm/ppc-pci.h> | ||
| 39 | #include <asm/firmware.h> | ||
| 40 | |||
| 41 | #ifdef DEBUG | ||
| 42 | #include <asm/udbg.h> | ||
| 43 | #define DBG(fmt...) printk(fmt) | ||
| 44 | #else | ||
| 45 | #define DBG(fmt...) | ||
| 46 | #endif | ||
| 47 | |||
| 48 | static DEFINE_SPINLOCK(hose_spinlock); | ||
| 49 | |||
| 50 | /* XXX kill that some day ... */ | ||
| 51 | int global_phb_number; /* Global phb counter */ | ||
| 52 | |||
| 53 | extern struct list_head hose_list; | ||
| 54 | |||
| 55 | /* | ||
| 56 | * pci_controller(phb) initialized common variables. | ||
| 57 | */ | ||
| 58 | static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||
| 59 | { | ||
| 60 | memset(hose, 0, sizeof(struct pci_controller)); | ||
| 61 | |||
| 62 | spin_lock(&hose_spinlock); | ||
| 63 | hose->global_number = global_phb_number++; | ||
| 64 | list_add_tail(&hose->list_node, &hose_list); | ||
| 65 | spin_unlock(&hose_spinlock); | ||
| 66 | } | ||
| 67 | |||
| 68 | struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||
| 69 | { | ||
| 70 | struct pci_controller *phb; | ||
| 71 | |||
| 72 | if (mem_init_done) | ||
| 73 | phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||
| 74 | else | ||
| 75 | phb = alloc_bootmem(sizeof (struct pci_controller)); | ||
| 76 | if (phb == NULL) | ||
| 77 | return NULL; | ||
| 78 | pci_setup_pci_controller(phb); | ||
| 79 | phb->arch_data = dev; | ||
| 80 | phb->is_dynamic = mem_init_done; | ||
| 81 | #ifdef CONFIG_PPC64 | ||
| 82 | if (dev) { | ||
| 83 | int nid = of_node_to_nid(dev); | ||
| 84 | |||
| 85 | if (nid < 0 || !node_online(nid)) | ||
| 86 | nid = -1; | ||
| 87 | |||
| 88 | PHB_SET_NODE(phb, nid); | ||
| 89 | } | ||
| 90 | #endif | ||
| 91 | return phb; | ||
| 92 | } | ||
| 93 | |||
| 94 | void pcibios_free_controller(struct pci_controller *phb) | ||
| 95 | { | ||
| 96 | spin_lock(&hose_spinlock); | ||
| 97 | list_del(&phb->list_node); | ||
| 98 | spin_unlock(&hose_spinlock); | ||
| 99 | |||
| 100 | if (phb->is_dynamic) | ||
| 101 | kfree(phb); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Return the domain number for this bus. | ||
| 106 | */ | ||
| 107 | int pci_domain_nr(struct pci_bus *bus) | ||
| 108 | { | ||
| 109 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 110 | return 0; | ||
| 111 | else { | ||
| 112 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
| 113 | |||
| 114 | return hose->global_number; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | EXPORT_SYMBOL(pci_domain_nr); | ||
| 119 | |||
| 120 | #ifdef CONFIG_PPC_OF | ||
| 121 | |||
| 122 | /* This routine is meant to be used early during boot, when the | ||
| 123 | * PCI bus numbers have not yet been assigned, and you need to | ||
| 124 | * issue PCI config cycles to an OF device. | ||
| 125 | * It could also be used to "fix" RTAS config cycles if you want | ||
| 126 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
| 127 | * config cycles. | ||
| 128 | */ | ||
| 129 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
| 130 | { | ||
| 131 | if (!have_of) | ||
| 132 | return NULL; | ||
| 133 | while(node) { | ||
| 134 | struct pci_controller *hose, *tmp; | ||
| 135 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
| 136 | if (hose->arch_data == node) | ||
| 137 | return hose; | ||
| 138 | node = node->parent; | ||
| 139 | } | ||
| 140 | return NULL; | ||
| 141 | } | ||
| 142 | |||
| 143 | static ssize_t pci_show_devspec(struct device *dev, | ||
| 144 | struct device_attribute *attr, char *buf) | ||
| 145 | { | ||
| 146 | struct pci_dev *pdev; | ||
| 147 | struct device_node *np; | ||
| 148 | |||
| 149 | pdev = to_pci_dev (dev); | ||
| 150 | np = pci_device_to_OF_node(pdev); | ||
| 151 | if (np == NULL || np->full_name == NULL) | ||
| 152 | return 0; | ||
| 153 | return sprintf(buf, "%s", np->full_name); | ||
| 154 | } | ||
| 155 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
| 156 | #endif /* CONFIG_PPC_OF */ | ||
| 157 | |||
| 158 | /* Add sysfs properties */ | ||
| 159 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
| 160 | { | ||
| 161 | #ifdef CONFIG_PPC_OF | ||
| 162 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
| 163 | #endif /* CONFIG_PPC_OF */ | ||
| 164 | } | ||
| 165 | |||
| 166 | char __init *pcibios_setup(char *str) | ||
| 167 | { | ||
| 168 | return str; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
| 173 | * If the interrupt is used, then gets the interrupt line from the | ||
| 174 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
| 175 | */ | ||
| 176 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
| 177 | { | ||
| 178 | struct of_irq oirq; | ||
| 179 | unsigned int virq; | ||
| 180 | |||
| 181 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
| 182 | |||
| 183 | #ifdef DEBUG | ||
| 184 | memset(&oirq, 0xff, sizeof(oirq)); | ||
| 185 | #endif | ||
| 186 | /* Try to get a mapping from the device-tree */ | ||
| 187 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
| 188 | u8 line, pin; | ||
| 189 | |||
| 190 | /* If that fails, lets fallback to what is in the config | ||
| 191 | * space and map that through the default controller. We | ||
| 192 | * also set the type to level low since that's what PCI | ||
| 193 | * interrupts are. If your platform does differently, then | ||
| 194 | * either provide a proper interrupt tree or don't use this | ||
| 195 | * function. | ||
| 196 | */ | ||
| 197 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
| 198 | return -1; | ||
| 199 | if (pin == 0) | ||
| 200 | return -1; | ||
| 201 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
| 202 | line == 0xff) { | ||
| 203 | return -1; | ||
| 204 | } | ||
| 205 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
| 206 | |||
| 207 | virq = irq_create_mapping(NULL, line); | ||
| 208 | if (virq != NO_IRQ) | ||
| 209 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
| 210 | } else { | ||
| 211 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
| 212 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
| 213 | oirq.controller->full_name); | ||
| 214 | |||
| 215 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
| 216 | oirq.size); | ||
| 217 | } | ||
| 218 | if(virq == NO_IRQ) { | ||
| 219 | DBG(" -> failed to map !\n"); | ||
| 220 | return -1; | ||
| 221 | } | ||
| 222 | |||
| 223 | DBG(" -> mapped to linux irq %d\n", virq); | ||
| 224 | |||
| 225 | pci_dev->irq = virq; | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | EXPORT_SYMBOL(pci_read_irq_line); | ||
| 230 | |||
| 231 | /* | ||
| 232 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
| 233 | * modelled on the sparc64 implementation by Dave Miller. | ||
| 234 | * -- paulus. | ||
| 235 | */ | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
| 239 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
| 240 | * | ||
| 241 | * Basically, the user finds the base address for his device which he wishes | ||
| 242 | * to mmap. They read the 32-bit value from the config space base register, | ||
| 243 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
| 244 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
| 245 | * | ||
| 246 | * Returns negative error code on failure, zero on success. | ||
| 247 | */ | ||
| 248 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
| 249 | resource_size_t *offset, | ||
| 250 | enum pci_mmap_state mmap_state) | ||
| 251 | { | ||
| 252 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 253 | unsigned long io_offset = 0; | ||
| 254 | int i, res_bit; | ||
| 255 | |||
| 256 | if (hose == 0) | ||
| 257 | return NULL; /* should never happen */ | ||
| 258 | |||
| 259 | /* If memory, add on the PCI bridge address offset */ | ||
| 260 | if (mmap_state == pci_mmap_mem) { | ||
| 261 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
| 262 | *offset += hose->pci_mem_offset; | ||
| 263 | #endif | ||
| 264 | res_bit = IORESOURCE_MEM; | ||
| 265 | } else { | ||
| 266 | io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
| 267 | *offset += io_offset; | ||
| 268 | res_bit = IORESOURCE_IO; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* | ||
| 272 | * Check that the offset requested corresponds to one of the | ||
| 273 | * resources of the device. | ||
| 274 | */ | ||
| 275 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 276 | struct resource *rp = &dev->resource[i]; | ||
| 277 | int flags = rp->flags; | ||
| 278 | |||
| 279 | /* treat ROM as memory (should be already) */ | ||
| 280 | if (i == PCI_ROM_RESOURCE) | ||
| 281 | flags |= IORESOURCE_MEM; | ||
| 282 | |||
| 283 | /* Active and same type? */ | ||
| 284 | if ((flags & res_bit) == 0) | ||
| 285 | continue; | ||
| 286 | |||
| 287 | /* In the range of this resource? */ | ||
| 288 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
| 289 | continue; | ||
| 290 | |||
| 291 | /* found it! construct the final physical address */ | ||
| 292 | if (mmap_state == pci_mmap_io) | ||
| 293 | *offset += hose->io_base_phys - io_offset; | ||
| 294 | return rp; | ||
| 295 | } | ||
| 296 | |||
| 297 | return NULL; | ||
| 298 | } | ||
| 299 | |||
| 300 | /* | ||
| 301 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
| 302 | * device mapping. | ||
| 303 | */ | ||
| 304 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
| 305 | pgprot_t protection, | ||
| 306 | enum pci_mmap_state mmap_state, | ||
| 307 | int write_combine) | ||
| 308 | { | ||
| 309 | unsigned long prot = pgprot_val(protection); | ||
| 310 | |||
| 311 | /* Write combine is always 0 on non-memory space mappings. On | ||
| 312 | * memory space, if the user didn't pass 1, we check for a | ||
| 313 | * "prefetchable" resource. This is a bit hackish, but we use | ||
| 314 | * this to workaround the inability of /sysfs to provide a write | ||
| 315 | * combine bit | ||
| 316 | */ | ||
| 317 | if (mmap_state != pci_mmap_mem) | ||
| 318 | write_combine = 0; | ||
| 319 | else if (write_combine == 0) { | ||
| 320 | if (rp->flags & IORESOURCE_PREFETCH) | ||
| 321 | write_combine = 1; | ||
| 322 | } | ||
| 323 | |||
| 324 | /* XXX would be nice to have a way to ask for write-through */ | ||
| 325 | prot |= _PAGE_NO_CACHE; | ||
| 326 | if (write_combine) | ||
| 327 | prot &= ~_PAGE_GUARDED; | ||
| 328 | else | ||
| 329 | prot |= _PAGE_GUARDED; | ||
| 330 | |||
| 331 | return __pgprot(prot); | ||
| 332 | } | ||
| 333 | |||
| 334 | /* | ||
| 335 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
| 336 | * PCI device, it tries to find the PCI device first and calls the | ||
| 337 | * above routine | ||
| 338 | */ | ||
| 339 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
| 340 | unsigned long pfn, | ||
| 341 | unsigned long size, | ||
| 342 | pgprot_t protection) | ||
| 343 | { | ||
| 344 | struct pci_dev *pdev = NULL; | ||
| 345 | struct resource *found = NULL; | ||
| 346 | unsigned long prot = pgprot_val(protection); | ||
| 347 | unsigned long offset = pfn << PAGE_SHIFT; | ||
| 348 | int i; | ||
| 349 | |||
| 350 | if (page_is_ram(pfn)) | ||
| 351 | return __pgprot(prot); | ||
| 352 | |||
| 353 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
| 354 | |||
| 355 | for_each_pci_dev(pdev) { | ||
| 356 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 357 | struct resource *rp = &pdev->resource[i]; | ||
| 358 | int flags = rp->flags; | ||
| 359 | |||
| 360 | /* Active and same type? */ | ||
| 361 | if ((flags & IORESOURCE_MEM) == 0) | ||
| 362 | continue; | ||
| 363 | /* In the range of this resource? */ | ||
| 364 | if (offset < (rp->start & PAGE_MASK) || | ||
| 365 | offset > rp->end) | ||
| 366 | continue; | ||
| 367 | found = rp; | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | if (found) | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | if (found) { | ||
| 374 | if (found->flags & IORESOURCE_PREFETCH) | ||
| 375 | prot &= ~_PAGE_GUARDED; | ||
| 376 | pci_dev_put(pdev); | ||
| 377 | } | ||
| 378 | |||
| 379 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
| 380 | |||
| 381 | return __pgprot(prot); | ||
| 382 | } | ||
| 383 | |||
| 384 | |||
| 385 | /* | ||
| 386 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
| 387 | * appropriate for this architecture. The region in the process to map | ||
| 388 | * is described by vm_start and vm_end members of VMA, the base physical | ||
| 389 | * address is found in vm_pgoff. | ||
| 390 | * The pci device structure is provided so that architectures may make mapping | ||
| 391 | * decisions on a per-device or per-bus basis. | ||
| 392 | * | ||
| 393 | * Returns a negative error code on failure, zero on success. | ||
| 394 | */ | ||
| 395 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 396 | enum pci_mmap_state mmap_state, int write_combine) | ||
| 397 | { | ||
| 398 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 399 | struct resource *rp; | ||
| 400 | int ret; | ||
| 401 | |||
| 402 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
| 403 | if (rp == NULL) | ||
| 404 | return -EINVAL; | ||
| 405 | |||
| 406 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
| 407 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
| 408 | vma->vm_page_prot, | ||
| 409 | mmap_state, write_combine); | ||
| 410 | |||
| 411 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
| 412 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
| 413 | |||
| 414 | return ret; | ||
| 415 | } | ||
| 416 | |||
| 417 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 418 | const struct resource *rsrc, | ||
| 419 | resource_size_t *start, resource_size_t *end) | ||
| 420 | { | ||
| 421 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 422 | resource_size_t offset = 0; | ||
| 423 | |||
| 424 | if (hose == NULL) | ||
| 425 | return; | ||
| 426 | |||
| 427 | if (rsrc->flags & IORESOURCE_IO) | ||
| 428 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
| 429 | |||
| 430 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
| 431 | * a BAR value because X is lame and expects to be able to use that | ||
| 432 | * to pass to /dev/mem ! | ||
| 433 | * | ||
| 434 | * That means that we'll have potentially 64 bits values where some | ||
| 435 | * userland apps only expect 32 (like X itself since it thinks only | ||
| 436 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
| 437 | * 32 bits CHRPs :-( | ||
| 438 | * | ||
| 439 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
| 440 | * has been fixed (and the fix spread enough), we can re-enable the | ||
| 441 | * 2 lines below and pass down a BAR value to userland. In that case | ||
| 442 | * we'll also have to re-enable the matching code in | ||
| 443 | * __pci_mmap_make_offset(). | ||
| 444 | * | ||
| 445 | * BenH. | ||
| 446 | */ | ||
| 447 | #if 0 | ||
| 448 | else if (rsrc->flags & IORESOURCE_MEM) | ||
| 449 | offset = hose->pci_mem_offset; | ||
| 450 | #endif | ||
| 451 | |||
| 452 | *start = rsrc->start - offset; | ||
| 453 | *end = rsrc->end - offset; | ||
| 454 | } | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index e66064b5093a..0adf077f3f3a 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
| @@ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map; | |||
| 55 | */ | 55 | */ |
| 56 | int pci_assign_all_buses; | 56 | int pci_assign_all_buses; |
| 57 | 57 | ||
| 58 | struct pci_controller* hose_head; | 58 | LIST_HEAD(hose_list); |
| 59 | struct pci_controller** hose_tail = &hose_head; | ||
| 60 | 59 | ||
| 61 | static int pci_bus_count; | 60 | static int pci_bus_count; |
| 62 | 61 | ||
| @@ -573,58 +572,6 @@ pcibios_assign_resources(void) | |||
| 573 | } | 572 | } |
| 574 | } | 573 | } |
| 575 | 574 | ||
| 576 | |||
| 577 | int | ||
| 578 | pcibios_enable_resources(struct pci_dev *dev, int mask) | ||
| 579 | { | ||
| 580 | u16 cmd, old_cmd; | ||
| 581 | int idx; | ||
| 582 | struct resource *r; | ||
| 583 | |||
| 584 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 585 | old_cmd = cmd; | ||
| 586 | for (idx=0; idx<6; idx++) { | ||
| 587 | /* Only set up the requested stuff */ | ||
| 588 | if (!(mask & (1<<idx))) | ||
| 589 | continue; | ||
| 590 | |||
| 591 | r = &dev->resource[idx]; | ||
| 592 | if (r->flags & IORESOURCE_UNSET) { | ||
| 593 | printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||
| 594 | return -EINVAL; | ||
| 595 | } | ||
| 596 | if (r->flags & IORESOURCE_IO) | ||
| 597 | cmd |= PCI_COMMAND_IO; | ||
| 598 | if (r->flags & IORESOURCE_MEM) | ||
| 599 | cmd |= PCI_COMMAND_MEMORY; | ||
| 600 | } | ||
| 601 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
| 602 | cmd |= PCI_COMMAND_MEMORY; | ||
| 603 | if (cmd != old_cmd) { | ||
| 604 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | ||
| 605 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 606 | } | ||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | static int next_controller_index; | ||
| 611 | |||
| 612 | struct pci_controller * __init | ||
| 613 | pcibios_alloc_controller(void) | ||
| 614 | { | ||
| 615 | struct pci_controller *hose; | ||
| 616 | |||
| 617 | hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); | ||
| 618 | memset(hose, 0, sizeof(struct pci_controller)); | ||
| 619 | |||
| 620 | *hose_tail = hose; | ||
| 621 | hose_tail = &hose->next; | ||
| 622 | |||
| 623 | hose->index = next_controller_index++; | ||
| 624 | |||
| 625 | return hose; | ||
| 626 | } | ||
| 627 | |||
| 628 | #ifdef CONFIG_PPC_OF | 575 | #ifdef CONFIG_PPC_OF |
| 629 | /* | 576 | /* |
| 630 | * Functions below are used on OpenFirmware machines. | 577 | * Functions below are used on OpenFirmware machines. |
| @@ -670,7 +617,7 @@ void | |||
| 670 | pcibios_make_OF_bus_map(void) | 617 | pcibios_make_OF_bus_map(void) |
| 671 | { | 618 | { |
| 672 | int i; | 619 | int i; |
| 673 | struct pci_controller* hose; | 620 | struct pci_controller *hose, *tmp; |
| 674 | struct property *map_prop; | 621 | struct property *map_prop; |
| 675 | struct device_node *dn; | 622 | struct device_node *dn; |
| 676 | 623 | ||
| @@ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void) | |||
| 687 | pci_to_OF_bus_map[i] = 0xff; | 634 | pci_to_OF_bus_map[i] = 0xff; |
| 688 | 635 | ||
| 689 | /* For each hose, we begin searching bridges */ | 636 | /* For each hose, we begin searching bridges */ |
| 690 | for(hose=hose_head; hose; hose=hose->next) { | 637 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
| 691 | struct device_node* node; | 638 | struct device_node* node; |
| 692 | node = (struct device_node *)hose->arch_data; | 639 | node = (struct device_node *)hose->arch_data; |
| 693 | if (!node) | 640 | if (!node) |
| @@ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) | |||
| 765 | 712 | ||
| 766 | /* Are we a root bus ? */ | 713 | /* Are we a root bus ? */ |
| 767 | if (bus->self == NULL || bus->parent == NULL) { | 714 | if (bus->self == NULL || bus->parent == NULL) { |
| 768 | struct pci_controller *hose = pci_bus_to_hose(bus->number); | 715 | struct pci_controller *hose = pci_bus_to_host(bus); |
| 769 | if (hose == NULL) | 716 | if (hose == NULL) |
| 770 | return NULL; | 717 | return NULL; |
| 771 | return of_node_get(hose->arch_data); | 718 | return of_node_get(hose->arch_data); |
| @@ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev) | |||
| 818 | } | 765 | } |
| 819 | EXPORT_SYMBOL(pci_device_to_OF_node); | 766 | EXPORT_SYMBOL(pci_device_to_OF_node); |
| 820 | 767 | ||
| 821 | /* This routine is meant to be used early during boot, when the | ||
| 822 | * PCI bus numbers have not yet been assigned, and you need to | ||
| 823 | * issue PCI config cycles to an OF device. | ||
| 824 | * It could also be used to "fix" RTAS config cycles if you want | ||
| 825 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
| 826 | * config cycles. | ||
| 827 | */ | ||
| 828 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
| 829 | { | ||
| 830 | if (!have_of) | ||
| 831 | return NULL; | ||
| 832 | while(node) { | ||
| 833 | struct pci_controller* hose; | ||
| 834 | for (hose=hose_head;hose;hose=hose->next) | ||
| 835 | if (hose->arch_data == node) | ||
| 836 | return hose; | ||
| 837 | node=node->parent; | ||
| 838 | } | ||
| 839 | return NULL; | ||
| 840 | } | ||
| 841 | |||
| 842 | static int | 768 | static int |
| 843 | find_OF_pci_device_filter(struct device_node* node, void* data) | 769 | find_OF_pci_device_filter(struct device_node* node, void* data) |
| 844 | { | 770 | { |
| @@ -1027,34 +953,12 @@ pci_create_OF_bus_map(void) | |||
| 1027 | } | 953 | } |
| 1028 | } | 954 | } |
| 1029 | 955 | ||
| 1030 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1031 | { | ||
| 1032 | struct pci_dev *pdev; | ||
| 1033 | struct device_node *np; | ||
| 1034 | |||
| 1035 | pdev = to_pci_dev (dev); | ||
| 1036 | np = pci_device_to_OF_node(pdev); | ||
| 1037 | if (np == NULL || np->full_name == NULL) | ||
| 1038 | return 0; | ||
| 1039 | return sprintf(buf, "%s", np->full_name); | ||
| 1040 | } | ||
| 1041 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
| 1042 | |||
| 1043 | #else /* CONFIG_PPC_OF */ | 956 | #else /* CONFIG_PPC_OF */ |
| 1044 | void pcibios_make_OF_bus_map(void) | 957 | void pcibios_make_OF_bus_map(void) |
| 1045 | { | 958 | { |
| 1046 | } | 959 | } |
| 1047 | #endif /* CONFIG_PPC_OF */ | 960 | #endif /* CONFIG_PPC_OF */ |
| 1048 | 961 | ||
| 1049 | /* Add sysfs properties */ | ||
| 1050 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
| 1051 | { | ||
| 1052 | #ifdef CONFIG_PPC_OF | ||
| 1053 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
| 1054 | #endif /* CONFIG_PPC_OF */ | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | |||
| 1058 | #ifdef CONFIG_PPC_PMAC | 962 | #ifdef CONFIG_PPC_PMAC |
| 1059 | /* | 963 | /* |
| 1060 | * This set of routines checks for PCI<->PCI bridges that have closed | 964 | * This set of routines checks for PCI<->PCI bridges that have closed |
| @@ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void) | |||
| 1269 | static int __init | 1173 | static int __init |
| 1270 | pcibios_init(void) | 1174 | pcibios_init(void) |
| 1271 | { | 1175 | { |
| 1272 | struct pci_controller *hose; | 1176 | struct pci_controller *hose, *tmp; |
| 1273 | struct pci_bus *bus; | 1177 | struct pci_bus *bus; |
| 1274 | int next_busno; | 1178 | int next_busno = 0; |
| 1275 | 1179 | ||
| 1276 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); | 1180 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); |
| 1277 | 1181 | ||
| 1278 | /* Scan all of the recorded PCI controllers. */ | 1182 | /* Scan all of the recorded PCI controllers. */ |
| 1279 | for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | 1183 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
| 1280 | if (pci_assign_all_buses) | 1184 | if (pci_assign_all_buses) |
| 1281 | hose->first_busno = next_busno; | 1185 | hose->first_busno = next_busno; |
| 1282 | hose->last_busno = 0xff; | 1186 | hose->last_busno = 0xff; |
| @@ -1319,12 +1223,6 @@ pcibios_init(void) | |||
| 1319 | 1223 | ||
| 1320 | subsys_initcall(pcibios_init); | 1224 | subsys_initcall(pcibios_init); |
| 1321 | 1225 | ||
| 1322 | unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, | ||
| 1323 | unsigned long start, unsigned long size) | ||
| 1324 | { | ||
| 1325 | return start; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | void __init pcibios_fixup_bus(struct pci_bus *bus) | 1226 | void __init pcibios_fixup_bus(struct pci_bus *bus) |
| 1329 | { | 1227 | { |
| 1330 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | 1228 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; |
| @@ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1342 | if (!res->flags) { | 1240 | if (!res->flags) { |
| 1343 | if (io_offset) | 1241 | if (io_offset) |
| 1344 | printk(KERN_ERR "I/O resource not set for host" | 1242 | printk(KERN_ERR "I/O resource not set for host" |
| 1345 | " bridge %d\n", hose->index); | 1243 | " bridge %d\n", hose->global_number); |
| 1346 | res->start = 0; | 1244 | res->start = 0; |
| 1347 | res->end = IO_SPACE_LIMIT; | 1245 | res->end = IO_SPACE_LIMIT; |
| 1348 | res->flags = IORESOURCE_IO; | 1246 | res->flags = IORESOURCE_IO; |
| @@ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1356 | if (i > 0) | 1254 | if (i > 0) |
| 1357 | continue; | 1255 | continue; |
| 1358 | printk(KERN_ERR "Memory resource not set for " | 1256 | printk(KERN_ERR "Memory resource not set for " |
| 1359 | "host bridge %d\n", hose->index); | 1257 | "host bridge %d\n", hose->global_number); |
| 1360 | res->start = hose->pci_mem_offset; | 1258 | res->start = hose->pci_mem_offset; |
| 1361 | res->end = ~0U; | 1259 | res->end = ~0U; |
| 1362 | res->flags = IORESOURCE_MEM; | 1260 | res->flags = IORESOURCE_MEM; |
| @@ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1370 | for (i = 0; i < 4; ++i) { | 1268 | for (i = 0; i < 4; ++i) { |
| 1371 | if ((res = bus->resource[i]) == NULL) | 1269 | if ((res = bus->resource[i]) == NULL) |
| 1372 | continue; | 1270 | continue; |
| 1373 | if (!res->flags) | 1271 | if (!res->flags || bus->self->transparent) |
| 1374 | continue; | 1272 | continue; |
| 1375 | if (io_offset && (res->flags & IORESOURCE_IO)) { | 1273 | if (io_offset && (res->flags & IORESOURCE_IO)) { |
| 1376 | res->start += io_offset; | 1274 | res->start += io_offset; |
| @@ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1395 | } | 1293 | } |
| 1396 | } | 1294 | } |
| 1397 | 1295 | ||
| 1398 | char __init *pcibios_setup(char *str) | ||
| 1399 | { | ||
| 1400 | return str; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | /* the next one is stolen from the alpha port... */ | 1296 | /* the next one is stolen from the alpha port... */ |
| 1404 | void __init | 1297 | void __init |
| 1405 | pcibios_update_irq(struct pci_dev *dev, int irq) | 1298 | pcibios_update_irq(struct pci_dev *dev, int irq) |
| @@ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq) | |||
| 1408 | /* XXX FIXME - update OF device tree node interrupt property */ | 1301 | /* XXX FIXME - update OF device tree node interrupt property */ |
| 1409 | } | 1302 | } |
| 1410 | 1303 | ||
| 1411 | #ifdef CONFIG_PPC_MERGE | ||
| 1412 | /* XXX This is a copy of the ppc64 version. This is temporary until we start | ||
| 1413 | * merging the 2 PCI layers | ||
| 1414 | */ | ||
| 1415 | /* | ||
| 1416 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
| 1417 | * If the interrupt is used, then gets the interrupt line from the | ||
| 1418 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
| 1419 | */ | ||
| 1420 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
| 1421 | { | ||
| 1422 | struct of_irq oirq; | ||
| 1423 | unsigned int virq; | ||
| 1424 | |||
| 1425 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
| 1426 | |||
| 1427 | /* Try to get a mapping from the device-tree */ | ||
| 1428 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
| 1429 | u8 line, pin; | ||
| 1430 | |||
| 1431 | /* If that fails, lets fallback to what is in the config | ||
| 1432 | * space and map that through the default controller. We | ||
| 1433 | * also set the type to level low since that's what PCI | ||
| 1434 | * interrupts are. If your platform does differently, then | ||
| 1435 | * either provide a proper interrupt tree or don't use this | ||
| 1436 | * function. | ||
| 1437 | */ | ||
| 1438 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
| 1439 | return -1; | ||
| 1440 | if (pin == 0) | ||
| 1441 | return -1; | ||
| 1442 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
| 1443 | line == 0xff) { | ||
| 1444 | return -1; | ||
| 1445 | } | ||
| 1446 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
| 1447 | |||
| 1448 | virq = irq_create_mapping(NULL, line); | ||
| 1449 | if (virq != NO_IRQ) | ||
| 1450 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
| 1451 | } else { | ||
| 1452 | DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", | ||
| 1453 | oirq.size, oirq.specifier[0], oirq.controller->full_name); | ||
| 1454 | |||
| 1455 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
| 1456 | oirq.size); | ||
| 1457 | } | ||
| 1458 | if(virq == NO_IRQ) { | ||
| 1459 | DBG(" -> failed to map !\n"); | ||
| 1460 | return -1; | ||
| 1461 | } | ||
| 1462 | pci_dev->irq = virq; | ||
| 1463 | |||
| 1464 | return 0; | ||
| 1465 | } | ||
| 1466 | EXPORT_SYMBOL(pci_read_irq_line); | ||
| 1467 | #endif /* CONFIG_PPC_MERGE */ | ||
| 1468 | |||
| 1469 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 1304 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
| 1470 | { | 1305 | { |
| 1471 | u16 cmd, old_cmd; | 1306 | u16 cmd, old_cmd; |
| @@ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
| 1497 | return 0; | 1332 | return 0; |
| 1498 | } | 1333 | } |
| 1499 | 1334 | ||
| 1500 | struct pci_controller* | 1335 | static struct pci_controller* |
| 1501 | pci_bus_to_hose(int bus) | 1336 | pci_bus_to_hose(int bus) |
| 1502 | { | 1337 | { |
| 1503 | struct pci_controller* hose = hose_head; | 1338 | struct pci_controller *hose, *tmp; |
| 1504 | 1339 | ||
| 1505 | for (; hose; hose = hose->next) | 1340 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
| 1506 | if (bus >= hose->first_busno && bus <= hose->last_busno) | 1341 | if (bus >= hose->first_busno && bus <= hose->last_busno) |
| 1507 | return hose; | 1342 | return hose; |
| 1508 | return NULL; | 1343 | return NULL; |
| 1509 | } | 1344 | } |
| 1510 | 1345 | ||
| 1511 | void __iomem * | ||
| 1512 | pci_bus_io_base(unsigned int bus) | ||
| 1513 | { | ||
| 1514 | struct pci_controller *hose; | ||
| 1515 | |||
| 1516 | hose = pci_bus_to_hose(bus); | ||
| 1517 | if (!hose) | ||
| 1518 | return NULL; | ||
| 1519 | return hose->io_base_virt; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | unsigned long | ||
| 1523 | pci_bus_io_base_phys(unsigned int bus) | ||
| 1524 | { | ||
| 1525 | struct pci_controller *hose; | ||
| 1526 | |||
| 1527 | hose = pci_bus_to_hose(bus); | ||
| 1528 | if (!hose) | ||
| 1529 | return 0; | ||
| 1530 | return hose->io_base_phys; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | unsigned long | ||
| 1534 | pci_bus_mem_base_phys(unsigned int bus) | ||
| 1535 | { | ||
| 1536 | struct pci_controller *hose; | ||
| 1537 | |||
| 1538 | hose = pci_bus_to_hose(bus); | ||
| 1539 | if (!hose) | ||
| 1540 | return 0; | ||
| 1541 | return hose->pci_mem_offset; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | unsigned long | ||
| 1545 | pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) | ||
| 1546 | { | ||
| 1547 | /* Hack alert again ! See comments in chrp_pci.c | ||
| 1548 | */ | ||
| 1549 | struct pci_controller* hose = | ||
| 1550 | (struct pci_controller *)pdev->sysdata; | ||
| 1551 | if (hose && res->flags & IORESOURCE_MEM) | ||
| 1552 | return res->start - hose->pci_mem_offset; | ||
| 1553 | /* We may want to do something with IOs here... */ | ||
| 1554 | return res->start; | ||
| 1555 | } | ||
| 1556 | |||
| 1557 | |||
| 1558 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
| 1559 | resource_size_t *offset, | ||
| 1560 | enum pci_mmap_state mmap_state) | ||
| 1561 | { | ||
| 1562 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
| 1563 | unsigned long io_offset = 0; | ||
| 1564 | int i, res_bit; | ||
| 1565 | |||
| 1566 | if (hose == 0) | ||
| 1567 | return NULL; /* should never happen */ | ||
| 1568 | |||
| 1569 | /* If memory, add on the PCI bridge address offset */ | ||
| 1570 | if (mmap_state == pci_mmap_mem) { | ||
| 1571 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
| 1572 | *offset += hose->pci_mem_offset; | ||
| 1573 | #endif | ||
| 1574 | res_bit = IORESOURCE_MEM; | ||
| 1575 | } else { | ||
| 1576 | io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; | ||
| 1577 | *offset += io_offset; | ||
| 1578 | res_bit = IORESOURCE_IO; | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | /* | ||
| 1582 | * Check that the offset requested corresponds to one of the | ||
| 1583 | * resources of the device. | ||
| 1584 | */ | ||
| 1585 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 1586 | struct resource *rp = &dev->resource[i]; | ||
| 1587 | int flags = rp->flags; | ||
| 1588 | |||
| 1589 | /* treat ROM as memory (should be already) */ | ||
| 1590 | if (i == PCI_ROM_RESOURCE) | ||
| 1591 | flags |= IORESOURCE_MEM; | ||
| 1592 | |||
| 1593 | /* Active and same type? */ | ||
| 1594 | if ((flags & res_bit) == 0) | ||
| 1595 | continue; | ||
| 1596 | |||
| 1597 | /* In the range of this resource? */ | ||
| 1598 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
| 1599 | continue; | ||
| 1600 | |||
| 1601 | /* found it! construct the final physical address */ | ||
| 1602 | if (mmap_state == pci_mmap_io) | ||
| 1603 | *offset += hose->io_base_phys - io_offset; | ||
| 1604 | return rp; | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | return NULL; | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | /* | ||
| 1611 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
| 1612 | * device mapping. | ||
| 1613 | */ | ||
| 1614 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
| 1615 | pgprot_t protection, | ||
| 1616 | enum pci_mmap_state mmap_state, | ||
| 1617 | int write_combine) | ||
| 1618 | { | ||
| 1619 | unsigned long prot = pgprot_val(protection); | ||
| 1620 | |||
| 1621 | /* Write combine is always 0 on non-memory space mappings. On | ||
| 1622 | * memory space, if the user didn't pass 1, we check for a | ||
| 1623 | * "prefetchable" resource. This is a bit hackish, but we use | ||
| 1624 | * this to workaround the inability of /sysfs to provide a write | ||
| 1625 | * combine bit | ||
| 1626 | */ | ||
| 1627 | if (mmap_state != pci_mmap_mem) | ||
| 1628 | write_combine = 0; | ||
| 1629 | else if (write_combine == 0) { | ||
| 1630 | if (rp->flags & IORESOURCE_PREFETCH) | ||
| 1631 | write_combine = 1; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | /* XXX would be nice to have a way to ask for write-through */ | ||
| 1635 | prot |= _PAGE_NO_CACHE; | ||
| 1636 | if (write_combine) | ||
| 1637 | prot &= ~_PAGE_GUARDED; | ||
| 1638 | else | ||
| 1639 | prot |= _PAGE_GUARDED; | ||
| 1640 | |||
| 1641 | return __pgprot(prot); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | /* | ||
| 1645 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
| 1646 | * PCI device, it tries to find the PCI device first and calls the | ||
| 1647 | * above routine | ||
| 1648 | */ | ||
| 1649 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
| 1650 | unsigned long pfn, | ||
| 1651 | unsigned long size, | ||
| 1652 | pgprot_t protection) | ||
| 1653 | { | ||
| 1654 | struct pci_dev *pdev = NULL; | ||
| 1655 | struct resource *found = NULL; | ||
| 1656 | unsigned long prot = pgprot_val(protection); | ||
| 1657 | unsigned long offset = pfn << PAGE_SHIFT; | ||
| 1658 | int i; | ||
| 1659 | |||
| 1660 | if (page_is_ram(pfn)) | ||
| 1661 | return __pgprot(prot); | ||
| 1662 | |||
| 1663 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
| 1664 | |||
| 1665 | for_each_pci_dev(pdev) { | ||
| 1666 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 1667 | struct resource *rp = &pdev->resource[i]; | ||
| 1668 | int flags = rp->flags; | ||
| 1669 | |||
| 1670 | /* Active and same type? */ | ||
| 1671 | if ((flags & IORESOURCE_MEM) == 0) | ||
| 1672 | continue; | ||
| 1673 | /* In the range of this resource? */ | ||
| 1674 | if (offset < (rp->start & PAGE_MASK) || | ||
| 1675 | offset > rp->end) | ||
| 1676 | continue; | ||
| 1677 | found = rp; | ||
| 1678 | break; | ||
| 1679 | } | ||
| 1680 | if (found) | ||
| 1681 | break; | ||
| 1682 | } | ||
| 1683 | if (found) { | ||
| 1684 | if (found->flags & IORESOURCE_PREFETCH) | ||
| 1685 | prot &= ~_PAGE_GUARDED; | ||
| 1686 | pci_dev_put(pdev); | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
| 1690 | |||
| 1691 | return __pgprot(prot); | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | |||
| 1695 | /* | ||
| 1696 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
| 1697 | * appropriate for this architecture. The region in the process to map | ||
| 1698 | * is described by vm_start and vm_end members of VMA, the base physical | ||
| 1699 | * address is found in vm_pgoff. | ||
| 1700 | * The pci device structure is provided so that architectures may make mapping | ||
| 1701 | * decisions on a per-device or per-bus basis. | ||
| 1702 | * | ||
| 1703 | * Returns a negative error code on failure, zero on success. | ||
| 1704 | */ | ||
| 1705 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 1706 | enum pci_mmap_state mmap_state, | ||
| 1707 | int write_combine) | ||
| 1708 | { | ||
| 1709 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 1710 | struct resource *rp; | ||
| 1711 | int ret; | ||
| 1712 | |||
| 1713 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
| 1714 | if (rp == NULL) | ||
| 1715 | return -EINVAL; | ||
| 1716 | |||
| 1717 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
| 1718 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
| 1719 | vma->vm_page_prot, | ||
| 1720 | mmap_state, write_combine); | ||
| 1721 | |||
| 1722 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
| 1723 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
| 1724 | |||
| 1725 | return ret; | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | /* Obsolete functions. Should be removed once the symbios driver | ||
| 1729 | * is fixed | ||
| 1730 | */ | ||
| 1731 | unsigned long | ||
| 1732 | phys_to_bus(unsigned long pa) | ||
| 1733 | { | ||
| 1734 | struct pci_controller *hose; | ||
| 1735 | int i; | ||
| 1736 | |||
| 1737 | for (hose = hose_head; hose; hose = hose->next) { | ||
| 1738 | for (i = 0; i < 3; ++i) { | ||
| 1739 | if (pa >= hose->mem_resources[i].start | ||
| 1740 | && pa <= hose->mem_resources[i].end) { | ||
| 1741 | /* | ||
| 1742 | * XXX the hose->pci_mem_offset really | ||
| 1743 | * only applies to mem_resources[0]. | ||
| 1744 | * We need a way to store an offset for | ||
| 1745 | * the others. -- paulus | ||
| 1746 | */ | ||
| 1747 | if (i == 0) | ||
| 1748 | pa -= hose->pci_mem_offset; | ||
| 1749 | return pa; | ||
| 1750 | } | ||
| 1751 | } | ||
| 1752 | } | ||
| 1753 | /* hmmm, didn't find it */ | ||
| 1754 | return 0; | ||
| 1755 | } | ||
| 1756 | |||
| 1757 | unsigned long | ||
| 1758 | pci_phys_to_bus(unsigned long pa, int busnr) | ||
| 1759 | { | ||
| 1760 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
| 1761 | if (!hose) | ||
| 1762 | return pa; | ||
| 1763 | return pa - hose->pci_mem_offset; | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | unsigned long | ||
| 1767 | pci_bus_to_phys(unsigned int ba, int busnr) | ||
| 1768 | { | ||
| 1769 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
| 1770 | if (!hose) | ||
| 1771 | return ba; | ||
| 1772 | return ba + hose->pci_mem_offset; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | /* Provide information on locations of various I/O regions in physical | 1346 | /* Provide information on locations of various I/O regions in physical |
| 1776 | * memory. Do this on a per-card basis so that we choose the right | 1347 | * memory. Do this on a per-card basis so that we choose the right |
| 1777 | * root bridge. | 1348 | * root bridge. |
| @@ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
| 1814 | return result; | 1385 | return result; |
| 1815 | } | 1386 | } |
| 1816 | 1387 | ||
| 1817 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 1818 | const struct resource *rsrc, | ||
| 1819 | resource_size_t *start, resource_size_t *end) | ||
| 1820 | { | ||
| 1821 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
| 1822 | resource_size_t offset = 0; | ||
| 1823 | |||
| 1824 | if (hose == NULL) | ||
| 1825 | return; | ||
| 1826 | |||
| 1827 | if (rsrc->flags & IORESOURCE_IO) | ||
| 1828 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
| 1829 | |||
| 1830 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
| 1831 | * a BAR value because X is lame and expects to be able to use that | ||
| 1832 | * to pass to /dev/mem ! | ||
| 1833 | * | ||
| 1834 | * That means that we'll have potentially 64 bits values where some | ||
| 1835 | * userland apps only expect 32 (like X itself since it thinks only | ||
| 1836 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
| 1837 | * 32 bits CHRPs :-( | ||
| 1838 | * | ||
| 1839 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
| 1840 | * has been fixed (and the fix spread enough), we can re-enable the | ||
| 1841 | * 2 lines below and pass down a BAR value to userland. In that case | ||
| 1842 | * we'll also have to re-enable the matching code in | ||
| 1843 | * __pci_mmap_make_offset(). | ||
| 1844 | * | ||
| 1845 | * BenH. | ||
| 1846 | */ | ||
| 1847 | #if 0 | ||
| 1848 | else if (rsrc->flags & IORESOURCE_MEM) | ||
| 1849 | offset = hose->pci_mem_offset; | ||
| 1850 | #endif | ||
| 1851 | |||
| 1852 | *start = rsrc->start - offset; | ||
| 1853 | *end = rsrc->end - offset; | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | void __init pci_init_resource(struct resource *res, resource_size_t start, | ||
| 1857 | resource_size_t end, int flags, char *name) | ||
| 1858 | { | ||
| 1859 | res->start = start; | ||
| 1860 | res->end = end; | ||
| 1861 | res->flags = flags; | ||
| 1862 | res->name = name; | ||
| 1863 | res->parent = NULL; | ||
| 1864 | res->sibling = NULL; | ||
| 1865 | res->child = NULL; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | unsigned long pci_address_to_pio(phys_addr_t address) | 1388 | unsigned long pci_address_to_pio(phys_addr_t address) |
| 1869 | { | 1389 | { |
| 1870 | struct pci_controller* hose = hose_head; | 1390 | struct pci_controller *hose, *tmp; |
| 1871 | 1391 | ||
| 1872 | for (; hose; hose = hose->next) { | 1392 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
| 1873 | unsigned int size = hose->io_resource.end - | 1393 | unsigned int size = hose->io_resource.end - |
| 1874 | hose->io_resource.start + 1; | 1394 | hose->io_resource.start + 1; |
| 1875 | if (address >= hose->io_base_phys && | 1395 | if (address >= hose->io_base_phys && |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 249cca27a9b8..93b2920effc5 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
| 23 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
| 24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| 25 | #include <linux/vmalloc.h> | ||
| 25 | 26 | ||
| 26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
| 27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| @@ -41,35 +42,23 @@ | |||
| 41 | 42 | ||
| 42 | unsigned long pci_probe_only = 1; | 43 | unsigned long pci_probe_only = 1; |
| 43 | int pci_assign_all_buses = 0; | 44 | int pci_assign_all_buses = 0; |
| 44 | static int pci_initial_scan_done; | ||
| 45 | 45 | ||
| 46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | 46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); |
| 47 | static void do_bus_setup(struct pci_bus *bus); | 47 | static void do_bus_setup(struct pci_bus *bus); |
| 48 | static void phbs_remap_io(void); | ||
| 49 | 48 | ||
| 50 | /* pci_io_base -- the base address from which io bars are offsets. | 49 | /* pci_io_base -- the base address from which io bars are offsets. |
| 51 | * This is the lowest I/O base address (so bar values are always positive), | 50 | * This is the lowest I/O base address (so bar values are always positive), |
| 52 | * and it *must* be the start of ISA space if an ISA bus exists because | 51 | * and it *must* be the start of ISA space if an ISA bus exists because |
| 53 | * ISA drivers use hard coded offsets. If no ISA bus exists a dummy | 52 | * ISA drivers use hard coded offsets. If no ISA bus exists nothing |
| 54 | * page is mapped and isa_io_limit prevents access to it. | 53 | * is mapped on the first 64K of IO space |
| 55 | */ | 54 | */ |
| 56 | unsigned long isa_io_base; /* NULL if no ISA bus */ | 55 | unsigned long pci_io_base = ISA_IO_BASE; |
| 57 | EXPORT_SYMBOL(isa_io_base); | ||
| 58 | unsigned long pci_io_base; | ||
| 59 | EXPORT_SYMBOL(pci_io_base); | 56 | EXPORT_SYMBOL(pci_io_base); |
| 60 | 57 | ||
| 61 | void iSeries_pcibios_init(void); | ||
| 62 | |||
| 63 | LIST_HEAD(hose_list); | 58 | LIST_HEAD(hose_list); |
| 64 | 59 | ||
| 65 | static struct dma_mapping_ops *pci_dma_ops; | 60 | static struct dma_mapping_ops *pci_dma_ops; |
| 66 | 61 | ||
| 67 | int global_phb_number; /* Global phb counter */ | ||
| 68 | |||
| 69 | /* Cached ISA bridge dev. */ | ||
| 70 | struct pci_dev *ppc64_isabridge_dev = NULL; | ||
| 71 | EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); | ||
| 72 | |||
| 73 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) | 62 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) |
| 74 | { | 63 | { |
| 75 | pci_dma_ops = dma_ops; | 64 | pci_dma_ops = dma_ops; |
| @@ -100,7 +89,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region | |||
| 100 | return; | 89 | return; |
| 101 | 90 | ||
| 102 | if (res->flags & IORESOURCE_IO) | 91 | if (res->flags & IORESOURCE_IO) |
| 103 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 92 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
| 104 | 93 | ||
| 105 | if (res->flags & IORESOURCE_MEM) | 94 | if (res->flags & IORESOURCE_MEM) |
| 106 | offset = hose->pci_mem_offset; | 95 | offset = hose->pci_mem_offset; |
| @@ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | |||
| 119 | return; | 108 | return; |
| 120 | 109 | ||
| 121 | if (res->flags & IORESOURCE_IO) | 110 | if (res->flags & IORESOURCE_IO) |
| 122 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 111 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
| 123 | 112 | ||
| 124 | if (res->flags & IORESOURCE_MEM) | 113 | if (res->flags & IORESOURCE_MEM) |
| 125 | offset = hose->pci_mem_offset; | 114 | offset = hose->pci_mem_offset; |
| @@ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
| 156 | 145 | ||
| 157 | if (res->flags & IORESOURCE_IO) { | 146 | if (res->flags & IORESOURCE_IO) { |
| 158 | unsigned long offset = (unsigned long)hose->io_base_virt - | 147 | unsigned long offset = (unsigned long)hose->io_base_virt - |
| 159 | pci_io_base; | 148 | _IO_BASE; |
| 160 | /* Make sure we start at our min on all hoses */ | 149 | /* Make sure we start at our min on all hoses */ |
| 161 | if (start - offset < PCIBIOS_MIN_IO) | 150 | if (start - offset < PCIBIOS_MIN_IO) |
| 162 | start = PCIBIOS_MIN_IO + offset; | 151 | start = PCIBIOS_MIN_IO + offset; |
| @@ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
| 180 | res->start = start; | 169 | res->start = start; |
| 181 | } | 170 | } |
| 182 | 171 | ||
| 183 | static DEFINE_SPINLOCK(hose_spinlock); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * pci_controller(phb) initialized common variables. | ||
| 187 | */ | ||
| 188 | static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||
| 189 | { | ||
| 190 | memset(hose, 0, sizeof(struct pci_controller)); | ||
| 191 | |||
| 192 | spin_lock(&hose_spinlock); | ||
| 193 | hose->global_number = global_phb_number++; | ||
| 194 | list_add_tail(&hose->list_node, &hose_list); | ||
| 195 | spin_unlock(&hose_spinlock); | ||
| 196 | } | ||
| 197 | |||
| 198 | struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||
| 199 | { | ||
| 200 | struct pci_controller *phb; | ||
| 201 | |||
| 202 | if (mem_init_done) | ||
| 203 | phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||
| 204 | else | ||
| 205 | phb = alloc_bootmem(sizeof (struct pci_controller)); | ||
| 206 | if (phb == NULL) | ||
| 207 | return NULL; | ||
| 208 | pci_setup_pci_controller(phb); | ||
| 209 | phb->arch_data = dev; | ||
| 210 | phb->is_dynamic = mem_init_done; | ||
| 211 | if (dev) { | ||
| 212 | int nid = of_node_to_nid(dev); | ||
| 213 | |||
| 214 | if (nid < 0 || !node_online(nid)) | ||
| 215 | nid = -1; | ||
| 216 | |||
| 217 | PHB_SET_NODE(phb, nid); | ||
| 218 | } | ||
| 219 | return phb; | ||
| 220 | } | ||
| 221 | |||
| 222 | void pcibios_free_controller(struct pci_controller *phb) | ||
| 223 | { | ||
| 224 | spin_lock(&hose_spinlock); | ||
| 225 | list_del(&phb->list_node); | ||
| 226 | spin_unlock(&hose_spinlock); | ||
| 227 | |||
| 228 | if (phb->is_dynamic) | ||
| 229 | kfree(phb); | ||
| 230 | } | ||
| 231 | |||
| 232 | void __devinit pcibios_claim_one_bus(struct pci_bus *b) | 172 | void __devinit pcibios_claim_one_bus(struct pci_bus *b) |
| 233 | { | 173 | { |
| 234 | struct pci_dev *dev; | 174 | struct pci_dev *dev; |
| @@ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0) | |||
| 291 | return flags; | 231 | return flags; |
| 292 | } | 232 | } |
| 293 | 233 | ||
| 294 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||
| 295 | 234 | ||
| 296 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | 235 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) |
| 297 | { | 236 | { |
| @@ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | |||
| 310 | flags = pci_parse_of_flags(addrs[0]); | 249 | flags = pci_parse_of_flags(addrs[0]); |
| 311 | if (!flags) | 250 | if (!flags) |
| 312 | continue; | 251 | continue; |
| 313 | base = GET_64BIT(addrs, 1); | 252 | base = of_read_number(&addrs[1], 2); |
| 314 | size = GET_64BIT(addrs, 3); | 253 | size = of_read_number(&addrs[3], 2); |
| 315 | if (!size) | 254 | if (!size) |
| 316 | continue; | 255 | continue; |
| 317 | i = addrs[0] & 0xff; | 256 | i = addrs[0] & 0xff; |
| @@ -477,7 +416,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
| 477 | i = 1; | 416 | i = 1; |
| 478 | for (; len >= 32; len -= 32, ranges += 8) { | 417 | for (; len >= 32; len -= 32, ranges += 8) { |
| 479 | flags = pci_parse_of_flags(ranges[0]); | 418 | flags = pci_parse_of_flags(ranges[0]); |
| 480 | size = GET_64BIT(ranges, 6); | 419 | size = of_read_number(&ranges[6], 2); |
| 481 | if (flags == 0 || size == 0) | 420 | if (flags == 0 || size == 0) |
| 482 | continue; | 421 | continue; |
| 483 | if (flags & IORESOURCE_IO) { | 422 | if (flags & IORESOURCE_IO) { |
| @@ -496,7 +435,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
| 496 | res = bus->resource[i]; | 435 | res = bus->resource[i]; |
| 497 | ++i; | 436 | ++i; |
| 498 | } | 437 | } |
| 499 | res->start = GET_64BIT(ranges, 1); | 438 | res->start = of_read_number(&ranges[1], 2); |
| 500 | res->end = res->start + size - 1; | 439 | res->end = res->start + size - 1; |
| 501 | res->flags = flags; | 440 | res->flags = flags; |
| 502 | fixup_resource(res, dev); | 441 | fixup_resource(res, dev); |
| @@ -535,10 +474,16 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
| 535 | bus->secondary = hose->first_busno; | 474 | bus->secondary = hose->first_busno; |
| 536 | hose->bus = bus; | 475 | hose->bus = bus; |
| 537 | 476 | ||
| 477 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 478 | pcibios_map_io_space(bus); | ||
| 479 | |||
| 538 | bus->resource[0] = res = &hose->io_resource; | 480 | bus->resource[0] = res = &hose->io_resource; |
| 539 | if (res->flags && request_resource(&ioport_resource, res)) | 481 | if (res->flags && request_resource(&ioport_resource, res)) { |
| 540 | printk(KERN_ERR "Failed to request PCI IO region " | 482 | printk(KERN_ERR "Failed to request PCI IO region " |
| 541 | "on PCI domain %04x\n", hose->global_number); | 483 | "on PCI domain %04x\n", hose->global_number); |
| 484 | DBG("res->start = 0x%016lx, res->end = 0x%016lx\n", | ||
| 485 | res->start, res->end); | ||
| 486 | } | ||
| 542 | 487 | ||
| 543 | for (i = 0; i < 3; ++i) { | 488 | for (i = 0; i < 3; ++i) { |
| 544 | res = &hose->mem_resources[i]; | 489 | res = &hose->mem_resources[i]; |
| @@ -596,17 +541,6 @@ static int __init pcibios_init(void) | |||
| 596 | if (ppc_md.pcibios_fixup) | 541 | if (ppc_md.pcibios_fixup) |
| 597 | ppc_md.pcibios_fixup(); | 542 | ppc_md.pcibios_fixup(); |
| 598 | 543 | ||
| 599 | /* Cache the location of the ISA bridge (if we have one) */ | ||
| 600 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); | ||
| 601 | if (ppc64_isabridge_dev != NULL) | ||
| 602 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | ||
| 603 | |||
| 604 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 605 | /* map in PCI I/O space */ | ||
| 606 | phbs_remap_io(); | ||
| 607 | |||
| 608 | pci_initial_scan_done = 1; | ||
| 609 | |||
| 610 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); | 544 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
| 611 | 545 | ||
| 612 | return 0; | 546 | return 0; |
| @@ -614,11 +548,6 @@ static int __init pcibios_init(void) | |||
| 614 | 548 | ||
| 615 | subsys_initcall(pcibios_init); | 549 | subsys_initcall(pcibios_init); |
| 616 | 550 | ||
| 617 | char __init *pcibios_setup(char *str) | ||
| 618 | { | ||
| 619 | return str; | ||
| 620 | } | ||
| 621 | |||
| 622 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 551 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
| 623 | { | 552 | { |
| 624 | u16 cmd, oldcmd; | 553 | u16 cmd, oldcmd; |
| @@ -649,22 +578,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
| 649 | return 0; | 578 | return 0; |
| 650 | } | 579 | } |
| 651 | 580 | ||
| 652 | /* | ||
| 653 | * Return the domain number for this bus. | ||
| 654 | */ | ||
| 655 | int pci_domain_nr(struct pci_bus *bus) | ||
| 656 | { | ||
| 657 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 658 | return 0; | ||
| 659 | else { | ||
| 660 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
| 661 | |||
| 662 | return hose->global_number; | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 666 | EXPORT_SYMBOL(pci_domain_nr); | ||
| 667 | |||
| 668 | /* Decide whether to display the domain number in /proc */ | 581 | /* Decide whether to display the domain number in /proc */ |
| 669 | int pci_proc_domain(struct pci_bus *bus) | 582 | int pci_proc_domain(struct pci_bus *bus) |
| 670 | { | 583 | { |
| @@ -676,281 +589,6 @@ int pci_proc_domain(struct pci_bus *bus) | |||
| 676 | } | 589 | } |
| 677 | } | 590 | } |
| 678 | 591 | ||
| 679 | /* | ||
| 680 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
| 681 | * modelled on the sparc64 implementation by Dave Miller. | ||
| 682 | * -- paulus. | ||
| 683 | */ | ||
| 684 | |||
| 685 | /* | ||
| 686 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
| 687 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
| 688 | * | ||
| 689 | * Basically, the user finds the base address for his device which he wishes | ||
| 690 | * to mmap. They read the 32-bit value from the config space base register, | ||
| 691 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
| 692 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
| 693 | * | ||
| 694 | * Returns negative error code on failure, zero on success. | ||
| 695 | */ | ||
| 696 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
| 697 | resource_size_t *offset, | ||
| 698 | enum pci_mmap_state mmap_state) | ||
| 699 | { | ||
| 700 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 701 | unsigned long io_offset = 0; | ||
| 702 | int i, res_bit; | ||
| 703 | |||
| 704 | if (hose == 0) | ||
| 705 | return NULL; /* should never happen */ | ||
| 706 | |||
| 707 | /* If memory, add on the PCI bridge address offset */ | ||
| 708 | if (mmap_state == pci_mmap_mem) { | ||
| 709 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
| 710 | *offset += hose->pci_mem_offset; | ||
| 711 | #endif | ||
| 712 | res_bit = IORESOURCE_MEM; | ||
| 713 | } else { | ||
| 714 | io_offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
| 715 | *offset += io_offset; | ||
| 716 | res_bit = IORESOURCE_IO; | ||
| 717 | } | ||
| 718 | |||
| 719 | /* | ||
| 720 | * Check that the offset requested corresponds to one of the | ||
| 721 | * resources of the device. | ||
| 722 | */ | ||
| 723 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 724 | struct resource *rp = &dev->resource[i]; | ||
| 725 | int flags = rp->flags; | ||
| 726 | |||
| 727 | /* treat ROM as memory (should be already) */ | ||
| 728 | if (i == PCI_ROM_RESOURCE) | ||
| 729 | flags |= IORESOURCE_MEM; | ||
| 730 | |||
| 731 | /* Active and same type? */ | ||
| 732 | if ((flags & res_bit) == 0) | ||
| 733 | continue; | ||
| 734 | |||
| 735 | /* In the range of this resource? */ | ||
| 736 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
| 737 | continue; | ||
| 738 | |||
| 739 | /* found it! construct the final physical address */ | ||
| 740 | if (mmap_state == pci_mmap_io) | ||
| 741 | *offset += hose->io_base_phys - io_offset; | ||
| 742 | return rp; | ||
| 743 | } | ||
| 744 | |||
| 745 | return NULL; | ||
| 746 | } | ||
| 747 | |||
| 748 | /* | ||
| 749 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
| 750 | * device mapping. | ||
| 751 | */ | ||
| 752 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
| 753 | pgprot_t protection, | ||
| 754 | enum pci_mmap_state mmap_state, | ||
| 755 | int write_combine) | ||
| 756 | { | ||
| 757 | unsigned long prot = pgprot_val(protection); | ||
| 758 | |||
| 759 | /* Write combine is always 0 on non-memory space mappings. On | ||
| 760 | * memory space, if the user didn't pass 1, we check for a | ||
| 761 | * "prefetchable" resource. This is a bit hackish, but we use | ||
| 762 | * this to workaround the inability of /sysfs to provide a write | ||
| 763 | * combine bit | ||
| 764 | */ | ||
| 765 | if (mmap_state != pci_mmap_mem) | ||
| 766 | write_combine = 0; | ||
| 767 | else if (write_combine == 0) { | ||
| 768 | if (rp->flags & IORESOURCE_PREFETCH) | ||
| 769 | write_combine = 1; | ||
| 770 | } | ||
| 771 | |||
| 772 | /* XXX would be nice to have a way to ask for write-through */ | ||
| 773 | prot |= _PAGE_NO_CACHE; | ||
| 774 | if (write_combine) | ||
| 775 | prot &= ~_PAGE_GUARDED; | ||
| 776 | else | ||
| 777 | prot |= _PAGE_GUARDED; | ||
| 778 | |||
| 779 | return __pgprot(prot); | ||
| 780 | } | ||
| 781 | |||
| 782 | /* | ||
| 783 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
| 784 | * PCI device, it tries to find the PCI device first and calls the | ||
| 785 | * above routine | ||
| 786 | */ | ||
| 787 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
| 788 | unsigned long pfn, | ||
| 789 | unsigned long size, | ||
| 790 | pgprot_t protection) | ||
| 791 | { | ||
| 792 | struct pci_dev *pdev = NULL; | ||
| 793 | struct resource *found = NULL; | ||
| 794 | unsigned long prot = pgprot_val(protection); | ||
| 795 | unsigned long offset = pfn << PAGE_SHIFT; | ||
| 796 | int i; | ||
| 797 | |||
| 798 | if (page_is_ram(pfn)) | ||
| 799 | return __pgprot(prot); | ||
| 800 | |||
| 801 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
| 802 | |||
| 803 | for_each_pci_dev(pdev) { | ||
| 804 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 805 | struct resource *rp = &pdev->resource[i]; | ||
| 806 | int flags = rp->flags; | ||
| 807 | |||
| 808 | /* Active and same type? */ | ||
| 809 | if ((flags & IORESOURCE_MEM) == 0) | ||
| 810 | continue; | ||
| 811 | /* In the range of this resource? */ | ||
| 812 | if (offset < (rp->start & PAGE_MASK) || | ||
| 813 | offset > rp->end) | ||
| 814 | continue; | ||
| 815 | found = rp; | ||
| 816 | break; | ||
| 817 | } | ||
| 818 | if (found) | ||
| 819 | break; | ||
| 820 | } | ||
| 821 | if (found) { | ||
| 822 | if (found->flags & IORESOURCE_PREFETCH) | ||
| 823 | prot &= ~_PAGE_GUARDED; | ||
| 824 | pci_dev_put(pdev); | ||
| 825 | } | ||
| 826 | |||
| 827 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
| 828 | |||
| 829 | return __pgprot(prot); | ||
| 830 | } | ||
| 831 | |||
| 832 | |||
| 833 | /* | ||
| 834 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
| 835 | * appropriate for this architecture. The region in the process to map | ||
| 836 | * is described by vm_start and vm_end members of VMA, the base physical | ||
| 837 | * address is found in vm_pgoff. | ||
| 838 | * The pci device structure is provided so that architectures may make mapping | ||
| 839 | * decisions on a per-device or per-bus basis. | ||
| 840 | * | ||
| 841 | * Returns a negative error code on failure, zero on success. | ||
| 842 | */ | ||
| 843 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 844 | enum pci_mmap_state mmap_state, int write_combine) | ||
| 845 | { | ||
| 846 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 847 | struct resource *rp; | ||
| 848 | int ret; | ||
| 849 | |||
| 850 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
| 851 | if (rp == NULL) | ||
| 852 | return -EINVAL; | ||
| 853 | |||
| 854 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
| 855 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
| 856 | vma->vm_page_prot, | ||
| 857 | mmap_state, write_combine); | ||
| 858 | |||
| 859 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
| 860 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
| 861 | |||
| 862 | return ret; | ||
| 863 | } | ||
| 864 | |||
| 865 | static ssize_t pci_show_devspec(struct device *dev, | ||
| 866 | struct device_attribute *attr, char *buf) | ||
| 867 | { | ||
| 868 | struct pci_dev *pdev; | ||
| 869 | struct device_node *np; | ||
| 870 | |||
| 871 | pdev = to_pci_dev (dev); | ||
| 872 | np = pci_device_to_OF_node(pdev); | ||
| 873 | if (np == NULL || np->full_name == NULL) | ||
| 874 | return 0; | ||
| 875 | return sprintf(buf, "%s", np->full_name); | ||
| 876 | } | ||
| 877 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
| 878 | |||
| 879 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
| 880 | { | ||
| 881 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
| 882 | } | ||
| 883 | |||
| 884 | #define ISA_SPACE_MASK 0x1 | ||
| 885 | #define ISA_SPACE_IO 0x1 | ||
| 886 | |||
| 887 | static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||
| 888 | unsigned long phb_io_base_phys, | ||
| 889 | void __iomem * phb_io_base_virt) | ||
| 890 | { | ||
| 891 | /* Remove these asap */ | ||
| 892 | |||
| 893 | struct pci_address { | ||
| 894 | u32 a_hi; | ||
| 895 | u32 a_mid; | ||
| 896 | u32 a_lo; | ||
| 897 | }; | ||
| 898 | |||
| 899 | struct isa_address { | ||
| 900 | u32 a_hi; | ||
| 901 | u32 a_lo; | ||
| 902 | }; | ||
| 903 | |||
| 904 | struct isa_range { | ||
| 905 | struct isa_address isa_addr; | ||
| 906 | struct pci_address pci_addr; | ||
| 907 | unsigned int size; | ||
| 908 | }; | ||
| 909 | |||
| 910 | const struct isa_range *range; | ||
| 911 | unsigned long pci_addr; | ||
| 912 | unsigned int isa_addr; | ||
| 913 | unsigned int size; | ||
| 914 | int rlen = 0; | ||
| 915 | |||
| 916 | range = of_get_property(isa_node, "ranges", &rlen); | ||
| 917 | if (range == NULL || (rlen < sizeof(struct isa_range))) { | ||
| 918 | printk(KERN_ERR "no ISA ranges or unexpected isa range size," | ||
| 919 | "mapping 64k\n"); | ||
| 920 | __ioremap_explicit(phb_io_base_phys, | ||
| 921 | (unsigned long)phb_io_base_virt, | ||
| 922 | 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
| 923 | return; | ||
| 924 | } | ||
| 925 | |||
| 926 | /* From "ISA Binding to 1275" | ||
| 927 | * The ranges property is laid out as an array of elements, | ||
| 928 | * each of which comprises: | ||
| 929 | * cells 0 - 1: an ISA address | ||
| 930 | * cells 2 - 4: a PCI address | ||
| 931 | * (size depending on dev->n_addr_cells) | ||
| 932 | * cell 5: the size of the range | ||
| 933 | */ | ||
| 934 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { | ||
| 935 | isa_addr = range->isa_addr.a_lo; | ||
| 936 | pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | | ||
| 937 | range->pci_addr.a_lo; | ||
| 938 | |||
| 939 | /* Assume these are both zero */ | ||
| 940 | if ((pci_addr != 0) || (isa_addr != 0)) { | ||
| 941 | printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||
| 942 | __FUNCTION__); | ||
| 943 | return; | ||
| 944 | } | ||
| 945 | |||
| 946 | size = PAGE_ALIGN(range->size); | ||
| 947 | |||
| 948 | __ioremap_explicit(phb_io_base_phys, | ||
| 949 | (unsigned long) phb_io_base_virt, | ||
| 950 | size, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | 592 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, |
| 955 | struct device_node *dev, int prim) | 593 | struct device_node *dev, int prim) |
| 956 | { | 594 | { |
| @@ -1045,155 +683,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
| 1045 | } | 683 | } |
| 1046 | } | 684 | } |
| 1047 | 685 | ||
| 1048 | void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary) | 686 | #ifdef CONFIG_HOTPLUG |
| 687 | |||
| 688 | int pcibios_unmap_io_space(struct pci_bus *bus) | ||
| 1049 | { | 689 | { |
| 1050 | unsigned long size = hose->pci_io_size; | 690 | struct pci_controller *hose; |
| 1051 | unsigned long io_virt_offset; | ||
| 1052 | struct resource *res; | ||
| 1053 | struct device_node *isa_dn; | ||
| 1054 | 691 | ||
| 1055 | if (size == 0) | 692 | WARN_ON(bus == NULL); |
| 1056 | return; | ||
| 1057 | 693 | ||
| 1058 | hose->io_base_virt = reserve_phb_iospace(size); | 694 | /* If this is not a PHB, we only flush the hash table over |
| 1059 | DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | 695 | * the area mapped by this bridge. We don't play with the PTE |
| 1060 | hose->global_number, hose->io_base_phys, | 696 | * mappings since we might have to deal with sub-page alignemnts |
| 1061 | (unsigned long) hose->io_base_virt); | 697 | * so flushing the hash table is the only sane way to make sure |
| 1062 | 698 | * that no hash entries are covering that removed bridge area | |
| 1063 | if (primary) { | 699 | * while still allowing other busses overlapping those pages |
| 1064 | pci_io_base = (unsigned long)hose->io_base_virt; | 700 | */ |
| 1065 | isa_dn = of_find_node_by_type(NULL, "isa"); | 701 | if (bus->self) { |
| 1066 | if (isa_dn) { | 702 | struct resource *res = bus->resource[0]; |
| 1067 | isa_io_base = pci_io_base; | ||
| 1068 | pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, | ||
| 1069 | hose->io_base_virt); | ||
| 1070 | of_node_put(isa_dn); | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | 703 | ||
| 1074 | io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | 704 | DBG("IO unmapping for PCI-PCI bridge %s\n", |
| 1075 | res = &hose->io_resource; | 705 | pci_name(bus->self)); |
| 1076 | res->start += io_virt_offset; | ||
| 1077 | res->end += io_virt_offset; | ||
| 1078 | 706 | ||
| 1079 | /* If this is called after the initial PCI scan, then we need to | 707 | __flush_hash_table_range(&init_mm, res->start + _IO_BASE, |
| 1080 | * proceed to IO mappings now | 708 | res->end - res->start + 1); |
| 1081 | */ | 709 | return 0; |
| 1082 | if (pci_initial_scan_done) | 710 | } |
| 1083 | __ioremap_explicit(hose->io_base_phys, | ||
| 1084 | (unsigned long)hose->io_base_virt, | ||
| 1085 | hose->pci_io_size, | ||
| 1086 | _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
| 1087 | } | ||
| 1088 | 711 | ||
| 1089 | void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose, | 712 | /* Get the host bridge */ |
| 1090 | int primary) | 713 | hose = pci_bus_to_host(bus); |
| 1091 | { | ||
| 1092 | unsigned long size = hose->pci_io_size; | ||
| 1093 | unsigned long io_virt_offset; | ||
| 1094 | struct resource *res; | ||
| 1095 | 714 | ||
| 1096 | if (size == 0) | 715 | /* Check if we have IOs allocated */ |
| 1097 | return; | 716 | if (hose->io_base_alloc == 0) |
| 717 | return 0; | ||
| 1098 | 718 | ||
| 1099 | hose->io_base_virt = __ioremap(hose->io_base_phys, size, | 719 | DBG("IO unmapping for PHB %s\n", |
| 1100 | _PAGE_NO_CACHE | _PAGE_GUARDED); | 720 | ((struct device_node *)hose->arch_data)->full_name); |
| 1101 | DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | 721 | DBG(" alloc=0x%p\n", hose->io_base_alloc); |
| 1102 | hose->global_number, hose->io_base_phys, | ||
| 1103 | (unsigned long) hose->io_base_virt); | ||
| 1104 | 722 | ||
| 1105 | if (primary) | 723 | /* This is a PHB, we fully unmap the IO area */ |
| 1106 | pci_io_base = (unsigned long)hose->io_base_virt; | 724 | vunmap(hose->io_base_alloc); |
| 1107 | 725 | ||
| 1108 | io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | 726 | return 0; |
| 1109 | res = &hose->io_resource; | ||
| 1110 | res->start += io_virt_offset; | ||
| 1111 | res->end += io_virt_offset; | ||
| 1112 | } | 727 | } |
| 728 | EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); | ||
| 1113 | 729 | ||
| 730 | #endif /* CONFIG_HOTPLUG */ | ||
| 1114 | 731 | ||
| 1115 | static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, | 732 | int __devinit pcibios_map_io_space(struct pci_bus *bus) |
| 1116 | unsigned long *start_virt, unsigned long *size) | ||
| 1117 | { | 733 | { |
| 1118 | struct pci_controller *hose = pci_bus_to_host(bus); | 734 | struct vm_struct *area; |
| 1119 | struct resource *res; | 735 | unsigned long phys_page; |
| 1120 | 736 | unsigned long size_page; | |
| 1121 | if (bus->self) | 737 | unsigned long io_virt_offset; |
| 1122 | res = bus->resource[0]; | 738 | struct pci_controller *hose; |
| 1123 | else | ||
| 1124 | /* Root Bus */ | ||
| 1125 | res = &hose->io_resource; | ||
| 1126 | |||
| 1127 | if (res->end == 0 && res->start == 0) | ||
| 1128 | return 1; | ||
| 1129 | 739 | ||
| 1130 | *start_virt = pci_io_base + res->start; | 740 | WARN_ON(bus == NULL); |
| 1131 | *start_phys = *start_virt + hose->io_base_phys | ||
| 1132 | - (unsigned long) hose->io_base_virt; | ||
| 1133 | 741 | ||
| 1134 | if (res->end > res->start) | 742 | /* If this not a PHB, nothing to do, page tables still exist and |
| 1135 | *size = res->end - res->start + 1; | 743 | * thus HPTEs will be faulted in when needed |
| 1136 | else { | 744 | */ |
| 1137 | printk("%s(): unexpected region 0x%lx->0x%lx\n", | 745 | if (bus->self) { |
| 1138 | __FUNCTION__, res->start, res->end); | 746 | DBG("IO mapping for PCI-PCI bridge %s\n", |
| 1139 | return 1; | 747 | pci_name(bus->self)); |
| 748 | DBG(" virt=0x%016lx...0x%016lx\n", | ||
| 749 | bus->resource[0]->start + _IO_BASE, | ||
| 750 | bus->resource[0]->end + _IO_BASE); | ||
| 751 | return 0; | ||
| 1140 | } | 752 | } |
| 1141 | 753 | ||
| 1142 | return 0; | 754 | /* Get the host bridge */ |
| 1143 | } | 755 | hose = pci_bus_to_host(bus); |
| 1144 | 756 | phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); | |
| 1145 | int unmap_bus_range(struct pci_bus *bus) | 757 | size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); |
| 1146 | { | ||
| 1147 | unsigned long start_phys; | ||
| 1148 | unsigned long start_virt; | ||
| 1149 | unsigned long size; | ||
| 1150 | 758 | ||
| 1151 | if (!bus) { | 759 | /* Make sure IO area address is clear */ |
| 1152 | printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | 760 | hose->io_base_alloc = NULL; |
| 1153 | return 1; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | ||
| 1157 | return 1; | ||
| 1158 | if (__iounmap_explicit((void __iomem *) start_virt, size)) | ||
| 1159 | return 1; | ||
| 1160 | |||
| 1161 | return 0; | ||
| 1162 | } | ||
| 1163 | EXPORT_SYMBOL(unmap_bus_range); | ||
| 1164 | 761 | ||
| 1165 | int remap_bus_range(struct pci_bus *bus) | 762 | /* If there's no IO to map on that bus, get away too */ |
| 1166 | { | 763 | if (hose->pci_io_size == 0 || hose->io_base_phys == 0) |
| 1167 | unsigned long start_phys; | 764 | return 0; |
| 1168 | unsigned long start_virt; | ||
| 1169 | unsigned long size; | ||
| 1170 | 765 | ||
| 1171 | if (!bus) { | 766 | /* Let's allocate some IO space for that guy. We don't pass |
| 1172 | printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | 767 | * VM_IOREMAP because we don't care about alignment tricks that |
| 1173 | return 1; | 768 | * the core does in that case. Maybe we should due to stupid card |
| 1174 | } | 769 | * with incomplete address decoding but I'd rather not deal with |
| 1175 | 770 | * those outside of the reserved 64K legacy region. | |
| 1176 | 771 | */ | |
| 1177 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | 772 | area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); |
| 1178 | return 1; | 773 | if (area == NULL) |
| 1179 | if (start_phys == 0) | 774 | return -ENOMEM; |
| 1180 | return 1; | 775 | hose->io_base_alloc = area->addr; |
| 1181 | printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | 776 | hose->io_base_virt = (void __iomem *)(area->addr + |
| 1182 | if (__ioremap_explicit(start_phys, start_virt, size, | 777 | hose->io_base_phys - phys_page); |
| 1183 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 778 | |
| 1184 | return 1; | 779 | DBG("IO mapping for PHB %s\n", |
| 780 | ((struct device_node *)hose->arch_data)->full_name); | ||
| 781 | DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n", | ||
| 782 | hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); | ||
| 783 | DBG(" size=0x%016lx (alloc=0x%016lx)\n", | ||
| 784 | hose->pci_io_size, size_page); | ||
| 785 | |||
| 786 | /* Establish the mapping */ | ||
| 787 | if (__ioremap_at(phys_page, area->addr, size_page, | ||
| 788 | _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL) | ||
| 789 | return -ENOMEM; | ||
| 790 | |||
| 791 | /* Fixup hose IO resource */ | ||
| 792 | io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
| 793 | hose->io_resource.start += io_virt_offset; | ||
| 794 | hose->io_resource.end += io_virt_offset; | ||
| 795 | |||
| 796 | DBG(" hose->io_resource=0x%016lx...0x%016lx\n", | ||
| 797 | hose->io_resource.start, hose->io_resource.end); | ||
| 1185 | 798 | ||
| 1186 | return 0; | 799 | return 0; |
| 1187 | } | 800 | } |
| 1188 | EXPORT_SYMBOL(remap_bus_range); | 801 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); |
| 1189 | |||
| 1190 | static void phbs_remap_io(void) | ||
| 1191 | { | ||
| 1192 | struct pci_controller *hose, *tmp; | ||
| 1193 | |||
| 1194 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
| 1195 | remap_bus_range(hose->bus); | ||
| 1196 | } | ||
| 1197 | 802 | ||
| 1198 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | 803 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) |
| 1199 | { | 804 | { |
| @@ -1201,8 +806,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | |||
| 1201 | unsigned long offset; | 806 | unsigned long offset; |
| 1202 | 807 | ||
| 1203 | if (res->flags & IORESOURCE_IO) { | 808 | if (res->flags & IORESOURCE_IO) { |
| 1204 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 809 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
| 1205 | |||
| 1206 | res->start += offset; | 810 | res->start += offset; |
| 1207 | res->end += offset; | 811 | res->end += offset; |
| 1208 | } else if (res->flags & IORESOURCE_MEM) { | 812 | } else if (res->flags & IORESOURCE_MEM) { |
| @@ -1217,9 +821,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | |||
| 1217 | /* Update device resources. */ | 821 | /* Update device resources. */ |
| 1218 | int i; | 822 | int i; |
| 1219 | 823 | ||
| 1220 | for (i = 0; i < PCI_NUM_RESOURCES; i++) | 824 | DBG("%s: Fixup resources:\n", pci_name(dev)); |
| 1221 | if (dev->resource[i].flags) | 825 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { |
| 1222 | fixup_resource(&dev->resource[i], dev); | 826 | struct resource *res = &dev->resource[i]; |
| 827 | if (!res->flags) | ||
| 828 | continue; | ||
| 829 | |||
| 830 | DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n", | ||
| 831 | i, res->flags, res->start, res->end); | ||
| 832 | |||
| 833 | fixup_resource(res, dev); | ||
| 834 | |||
| 835 | DBG(" > %08lx:0x%016lx...0x%016lx\n", | ||
| 836 | res->flags, res->start, res->end); | ||
| 837 | } | ||
| 1223 | } | 838 | } |
| 1224 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 839 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
| 1225 | 840 | ||
| @@ -1289,119 +904,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1289 | } | 904 | } |
| 1290 | EXPORT_SYMBOL(pcibios_fixup_bus); | 905 | EXPORT_SYMBOL(pcibios_fixup_bus); |
| 1291 | 906 | ||
| 1292 | /* | ||
| 1293 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
| 1294 | * If the interrupt is used, then gets the interrupt line from the | ||
| 1295 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
| 1296 | */ | ||
| 1297 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
| 1298 | { | ||
| 1299 | struct of_irq oirq; | ||
| 1300 | unsigned int virq; | ||
| 1301 | |||
| 1302 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
| 1303 | |||
| 1304 | #ifdef DEBUG | ||
| 1305 | memset(&oirq, 0xff, sizeof(oirq)); | ||
| 1306 | #endif | ||
| 1307 | /* Try to get a mapping from the device-tree */ | ||
| 1308 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
| 1309 | u8 line, pin; | ||
| 1310 | |||
| 1311 | /* If that fails, lets fallback to what is in the config | ||
| 1312 | * space and map that through the default controller. We | ||
| 1313 | * also set the type to level low since that's what PCI | ||
| 1314 | * interrupts are. If your platform does differently, then | ||
| 1315 | * either provide a proper interrupt tree or don't use this | ||
| 1316 | * function. | ||
| 1317 | */ | ||
| 1318 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
| 1319 | return -1; | ||
| 1320 | if (pin == 0) | ||
| 1321 | return -1; | ||
| 1322 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
| 1323 | line == 0xff) { | ||
| 1324 | return -1; | ||
| 1325 | } | ||
| 1326 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
| 1327 | |||
| 1328 | virq = irq_create_mapping(NULL, line); | ||
| 1329 | if (virq != NO_IRQ) | ||
| 1330 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
| 1331 | } else { | ||
| 1332 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
| 1333 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
| 1334 | oirq.controller->full_name); | ||
| 1335 | |||
| 1336 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
| 1337 | oirq.size); | ||
| 1338 | } | ||
| 1339 | if(virq == NO_IRQ) { | ||
| 1340 | DBG(" -> failed to map !\n"); | ||
| 1341 | return -1; | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | DBG(" -> mapped to linux irq %d\n", virq); | ||
| 1345 | |||
| 1346 | pci_dev->irq = virq; | ||
| 1347 | |||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | EXPORT_SYMBOL(pci_read_irq_line); | ||
| 1351 | |||
| 1352 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 1353 | const struct resource *rsrc, | ||
| 1354 | resource_size_t *start, resource_size_t *end) | ||
| 1355 | { | ||
| 1356 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 1357 | resource_size_t offset = 0; | ||
| 1358 | |||
| 1359 | if (hose == NULL) | ||
| 1360 | return; | ||
| 1361 | |||
| 1362 | if (rsrc->flags & IORESOURCE_IO) | ||
| 1363 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
| 1364 | |||
| 1365 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
| 1366 | * a BAR value because X is lame and expects to be able to use that | ||
| 1367 | * to pass to /dev/mem ! | ||
| 1368 | * | ||
| 1369 | * That means that we'll have potentially 64 bits values where some | ||
| 1370 | * userland apps only expect 32 (like X itself since it thinks only | ||
| 1371 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
| 1372 | * 32 bits CHRPs :-( | ||
| 1373 | * | ||
| 1374 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
| 1375 | * has been fixed (and the fix spread enough), we can re-enable the | ||
| 1376 | * 2 lines below and pass down a BAR value to userland. In that case | ||
| 1377 | * we'll also have to re-enable the matching code in | ||
| 1378 | * __pci_mmap_make_offset(). | ||
| 1379 | * | ||
| 1380 | * BenH. | ||
| 1381 | */ | ||
| 1382 | #if 0 | ||
| 1383 | else if (rsrc->flags & IORESOURCE_MEM) | ||
| 1384 | offset = hose->pci_mem_offset; | ||
| 1385 | #endif | ||
| 1386 | |||
| 1387 | *start = rsrc->start - offset; | ||
| 1388 | *end = rsrc->end - offset; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
| 1392 | { | ||
| 1393 | if (!have_of) | ||
| 1394 | return NULL; | ||
| 1395 | while(node) { | ||
| 1396 | struct pci_controller *hose, *tmp; | ||
| 1397 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
| 1398 | if (hose->arch_data == node) | ||
| 1399 | return hose; | ||
| 1400 | node = node->parent; | ||
| 1401 | } | ||
| 1402 | return NULL; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | unsigned long pci_address_to_pio(phys_addr_t address) | 907 | unsigned long pci_address_to_pio(phys_addr_t address) |
| 1406 | { | 908 | { |
| 1407 | struct pci_controller *hose, *tmp; | 909 | struct pci_controller *hose, *tmp; |
| @@ -1410,7 +912,7 @@ unsigned long pci_address_to_pio(phys_addr_t address) | |||
| 1410 | if (address >= hose->io_base_phys && | 912 | if (address >= hose->io_base_phys && |
| 1411 | address < (hose->io_base_phys + hose->pci_io_size)) { | 913 | address < (hose->io_base_phys + hose->pci_io_size)) { |
| 1412 | unsigned long base = | 914 | unsigned long base = |
| 1413 | (unsigned long)hose->io_base_virt - pci_io_base; | 915 | (unsigned long)hose->io_base_virt - _IO_BASE; |
| 1414 | return base + (address - hose->io_base_phys); | 916 | return base + (address - hose->io_base_phys); |
| 1415 | } | 917 | } |
| 1416 | } | 918 | } |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index c96fa9bd35a4..a20f1951a5ce 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
| @@ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | |||
| 67 | EXPORT_SYMBOL(DMA_MODE_READ); | 67 | EXPORT_SYMBOL(DMA_MODE_READ); |
| 68 | EXPORT_SYMBOL(DMA_MODE_WRITE); | 68 | EXPORT_SYMBOL(DMA_MODE_WRITE); |
| 69 | 69 | ||
| 70 | EXPORT_SYMBOL(do_signal); | ||
| 71 | EXPORT_SYMBOL(transfer_to_handler); | 70 | EXPORT_SYMBOL(transfer_to_handler); |
| 72 | EXPORT_SYMBOL(do_IRQ); | 71 | EXPORT_SYMBOL(do_IRQ); |
| 73 | EXPORT_SYMBOL(machine_check_exception); | 72 | EXPORT_SYMBOL(machine_check_exception); |
| @@ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base); | |||
| 106 | EXPORT_SYMBOL(pci_dram_offset); | 105 | EXPORT_SYMBOL(pci_dram_offset); |
| 107 | EXPORT_SYMBOL(pci_alloc_consistent); | 106 | EXPORT_SYMBOL(pci_alloc_consistent); |
| 108 | EXPORT_SYMBOL(pci_free_consistent); | 107 | EXPORT_SYMBOL(pci_free_consistent); |
| 109 | EXPORT_SYMBOL(pci_bus_io_base); | ||
| 110 | EXPORT_SYMBOL(pci_bus_io_base_phys); | ||
| 111 | EXPORT_SYMBOL(pci_bus_mem_base_phys); | ||
| 112 | EXPORT_SYMBOL(pci_bus_to_hose); | ||
| 113 | #endif /* CONFIG_PCI */ | 108 | #endif /* CONFIG_PCI */ |
| 114 | 109 | ||
| 115 | EXPORT_SYMBOL(start_thread); | 110 | EXPORT_SYMBOL(start_thread); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6e2f03566b0d..84f000a45e36 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -219,22 +219,26 @@ void discard_lazy_cpu_state(void) | |||
| 219 | } | 219 | } |
| 220 | #endif /* CONFIG_SMP */ | 220 | #endif /* CONFIG_SMP */ |
| 221 | 221 | ||
| 222 | #ifdef CONFIG_PPC_MERGE /* XXX for now */ | ||
| 223 | int set_dabr(unsigned long dabr) | 222 | int set_dabr(unsigned long dabr) |
| 224 | { | 223 | { |
| 224 | #ifdef CONFIG_PPC_MERGE /* XXX for now */ | ||
| 225 | if (ppc_md.set_dabr) | 225 | if (ppc_md.set_dabr) |
| 226 | return ppc_md.set_dabr(dabr); | 226 | return ppc_md.set_dabr(dabr); |
| 227 | #endif | ||
| 227 | 228 | ||
| 229 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ | ||
| 230 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | ||
| 228 | mtspr(SPRN_DABR, dabr); | 231 | mtspr(SPRN_DABR, dabr); |
| 232 | #endif | ||
| 229 | return 0; | 233 | return 0; |
| 230 | } | 234 | } |
| 231 | #endif | ||
| 232 | 235 | ||
| 233 | #ifdef CONFIG_PPC64 | 236 | #ifdef CONFIG_PPC64 |
| 234 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | 237 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); |
| 235 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
| 236 | #endif | 238 | #endif |
| 237 | 239 | ||
| 240 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
| 241 | |||
| 238 | struct task_struct *__switch_to(struct task_struct *prev, | 242 | struct task_struct *__switch_to(struct task_struct *prev, |
| 239 | struct task_struct *new) | 243 | struct task_struct *new) |
| 240 | { | 244 | { |
| @@ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 299 | 303 | ||
| 300 | #endif /* CONFIG_SMP */ | 304 | #endif /* CONFIG_SMP */ |
| 301 | 305 | ||
| 302 | #ifdef CONFIG_PPC64 /* for now */ | ||
| 303 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { | 306 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { |
| 304 | set_dabr(new->thread.dabr); | 307 | set_dabr(new->thread.dabr); |
| 305 | __get_cpu_var(current_dabr) = new->thread.dabr; | 308 | __get_cpu_var(current_dabr) = new->thread.dabr; |
| 306 | } | 309 | } |
| 307 | #endif /* CONFIG_PPC64 */ | ||
| 308 | 310 | ||
| 309 | new_thread = &new->thread; | 311 | new_thread = &new->thread; |
| 310 | old_thread = ¤t->thread; | 312 | old_thread = ¤t->thread; |
| @@ -473,12 +475,10 @@ void flush_thread(void) | |||
| 473 | 475 | ||
| 474 | discard_lazy_cpu_state(); | 476 | discard_lazy_cpu_state(); |
| 475 | 477 | ||
| 476 | #ifdef CONFIG_PPC64 /* for now */ | ||
| 477 | if (current->thread.dabr) { | 478 | if (current->thread.dabr) { |
| 478 | current->thread.dabr = 0; | 479 | current->thread.dabr = 0; |
| 479 | set_dabr(0); | 480 | set_dabr(0); |
| 480 | } | 481 | } |
| 481 | #endif | ||
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | void | 484 | void |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index af42ddab3ab4..37ff99bd98b4 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <asm/pSeries_reconfig.h> | 52 | #include <asm/pSeries_reconfig.h> |
| 53 | #include <asm/pci-bridge.h> | 53 | #include <asm/pci-bridge.h> |
| 54 | #include <asm/kexec.h> | 54 | #include <asm/kexec.h> |
| 55 | #include <asm/system.h> | ||
| 55 | 56 | ||
| 56 | #ifdef DEBUG | 57 | #ifdef DEBUG |
| 57 | #define DBG(fmt...) printk(KERN_ERR fmt) | 58 | #define DBG(fmt...) printk(KERN_ERR fmt) |
| @@ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void) | |||
| 1005 | 1006 | ||
| 1006 | void __init early_init_devtree(void *params) | 1007 | void __init early_init_devtree(void *params) |
| 1007 | { | 1008 | { |
| 1008 | DBG(" -> early_init_devtree()\n"); | 1009 | DBG(" -> early_init_devtree(%p)\n", params); |
| 1009 | 1010 | ||
| 1010 | /* Setup flat device-tree pointer */ | 1011 | /* Setup flat device-tree pointer */ |
| 1011 | initial_boot_params = params; | 1012 | initial_boot_params = params; |
| @@ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params) | |||
| 1055 | DBG(" <- early_init_devtree()\n"); | 1056 | DBG(" <- early_init_devtree()\n"); |
| 1056 | } | 1057 | } |
| 1057 | 1058 | ||
| 1058 | #undef printk | ||
| 1059 | |||
| 1060 | int of_n_addr_cells(struct device_node* np) | 1059 | int of_n_addr_cells(struct device_node* np) |
| 1061 | { | 1060 | { |
| 1062 | const int *ip; | 1061 | const int *ip; |
| @@ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref) | |||
| 1375 | struct device_node *node = kref_to_device_node(kref); | 1374 | struct device_node *node = kref_to_device_node(kref); |
| 1376 | struct property *prop = node->properties; | 1375 | struct property *prop = node->properties; |
| 1377 | 1376 | ||
| 1378 | if (!OF_IS_DYNAMIC(node)) | 1377 | /* We should never be releasing nodes that haven't been detached. */ |
| 1378 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
| 1379 | printk("WARNING: Bad of_node_put() on %s\n", node->full_name); | ||
| 1380 | dump_stack(); | ||
| 1381 | kref_init(&node->kref); | ||
| 1382 | return; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
| 1379 | return; | 1386 | return; |
| 1387 | |||
| 1380 | while (prop) { | 1388 | while (prop) { |
| 1381 | struct property *next = prop->next; | 1389 | struct property *next = prop->next; |
| 1382 | kfree(prop->name); | 1390 | kfree(prop->name); |
| @@ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np) | |||
| 1432 | write_lock(&devtree_lock); | 1440 | write_lock(&devtree_lock); |
| 1433 | 1441 | ||
| 1434 | parent = np->parent; | 1442 | parent = np->parent; |
| 1443 | if (!parent) | ||
| 1444 | goto out_unlock; | ||
| 1435 | 1445 | ||
| 1436 | if (allnodes == np) | 1446 | if (allnodes == np) |
| 1437 | allnodes = np->allnext; | 1447 | allnodes = np->allnext; |
| @@ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np) | |||
| 1455 | prevsib->sibling = np->sibling; | 1465 | prevsib->sibling = np->sibling; |
| 1456 | } | 1466 | } |
| 1457 | 1467 | ||
| 1468 | of_node_set_flag(np, OF_DETACHED); | ||
| 1469 | |||
| 1470 | out_unlock: | ||
| 1458 | write_unlock(&devtree_lock); | 1471 | write_unlock(&devtree_lock); |
| 1459 | } | 1472 | } |
| 1460 | 1473 | ||
| @@ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | |||
| 1716 | } | 1729 | } |
| 1717 | EXPORT_SYMBOL(of_get_cpu_node); | 1730 | EXPORT_SYMBOL(of_get_cpu_node); |
| 1718 | 1731 | ||
| 1719 | #ifdef DEBUG | 1732 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) |
| 1720 | static struct debugfs_blob_wrapper flat_dt_blob; | 1733 | static struct debugfs_blob_wrapper flat_dt_blob; |
| 1721 | 1734 | ||
| 1722 | static int __init export_flat_device_tree(void) | 1735 | static int __init export_flat_device_tree(void) |
| 1723 | { | 1736 | { |
| 1724 | struct dentry *d; | 1737 | struct dentry *d; |
| 1725 | 1738 | ||
| 1726 | d = debugfs_create_dir("powerpc", NULL); | ||
| 1727 | if (!d) | ||
| 1728 | return 1; | ||
| 1729 | |||
| 1730 | flat_dt_blob.data = initial_boot_params; | 1739 | flat_dt_blob.data = initial_boot_params; |
| 1731 | flat_dt_blob.size = initial_boot_params->totalsize; | 1740 | flat_dt_blob.size = initial_boot_params->totalsize; |
| 1732 | 1741 | ||
| 1733 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, | 1742 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, |
| 1734 | d, &flat_dt_blob); | 1743 | powerpc_debugfs_root, &flat_dt_blob); |
| 1735 | if (!d) | 1744 | if (!d) |
| 1736 | return 1; | 1745 | return 1; |
| 1737 | 1746 | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d6047c441034..a1d582e38627 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -635,6 +635,7 @@ static void __init early_cmdline_parse(void) | |||
| 635 | /* ibm,dynamic-reconfiguration-memory property supported */ | 635 | /* ibm,dynamic-reconfiguration-memory property supported */ |
| 636 | #define OV5_DRCONF_MEMORY 0x20 | 636 | #define OV5_DRCONF_MEMORY 0x20 |
| 637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ | 637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ |
| 638 | #define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */ | ||
| 638 | /* PCIe/MSI support. Without MSI full PCIe is not supported */ | 639 | /* PCIe/MSI support. Without MSI full PCIe is not supported */ |
| 639 | #ifdef CONFIG_PCI_MSI | 640 | #ifdef CONFIG_PCI_MSI |
| 640 | #define OV5_MSI 0x01 /* PCIe/MSI support */ | 641 | #define OV5_MSI 0x01 /* PCIe/MSI support */ |
| @@ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = { | |||
| 685 | /* option vector 5: PAPR/OF options */ | 686 | /* option vector 5: PAPR/OF options */ |
| 686 | 3 - 2, /* length */ | 687 | 3 - 2, /* length */ |
| 687 | 0, /* don't ignore, don't halt */ | 688 | 0, /* don't ignore, don't halt */ |
| 688 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, | 689 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | |
| 690 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, | ||
| 689 | }; | 691 | }; |
| 690 | 692 | ||
| 691 | /* Old method - ELF header with PT_NOTE sections */ | 693 | /* Old method - ELF header with PT_NOTE sections */ |
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h deleted file mode 100644 index 8797ae737a7b..000000000000 --- a/arch/powerpc/kernel/ptrace-common.h +++ /dev/null | |||
| @@ -1,161 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration | ||
| 3 | * Extracted from ptrace.c and ptrace32.c | ||
| 4 | * | ||
| 5 | * This file is subject to the terms and conditions of the GNU General | ||
| 6 | * Public License. See the file README.legal in the main directory of | ||
| 7 | * this archive for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _PPC64_PTRACE_COMMON_H | ||
| 11 | #define _PPC64_PTRACE_COMMON_H | ||
| 12 | |||
| 13 | #include <asm/system.h> | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Set of msr bits that gdb can change on behalf of a process. | ||
| 17 | */ | ||
| 18 | #define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Get contents of register REGNO in task TASK. | ||
| 22 | */ | ||
| 23 | static inline unsigned long get_reg(struct task_struct *task, int regno) | ||
| 24 | { | ||
| 25 | unsigned long tmp = 0; | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Put the correct FP bits in, they might be wrong as a result | ||
| 29 | * of our lazy FP restore. | ||
| 30 | */ | ||
| 31 | if (regno == PT_MSR) { | ||
| 32 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||
| 33 | tmp |= task->thread.fpexc_mode; | ||
| 34 | } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { | ||
| 35 | tmp = ((unsigned long *)task->thread.regs)[regno]; | ||
| 36 | } | ||
| 37 | |||
| 38 | return tmp; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Write contents of register REGNO in task TASK. | ||
| 43 | */ | ||
| 44 | static inline int put_reg(struct task_struct *task, int regno, | ||
| 45 | unsigned long data) | ||
| 46 | { | ||
| 47 | if (regno < PT_SOFTE) { | ||
| 48 | if (regno == PT_MSR) | ||
| 49 | data = (data & MSR_DEBUGCHANGE) | ||
| 50 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||
| 51 | ((unsigned long *)task->thread.regs)[regno] = data; | ||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | return -EIO; | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline void set_single_step(struct task_struct *task) | ||
| 58 | { | ||
| 59 | struct pt_regs *regs = task->thread.regs; | ||
| 60 | if (regs != NULL) | ||
| 61 | regs->msr |= MSR_SE; | ||
| 62 | set_tsk_thread_flag(task, TIF_SINGLESTEP); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void clear_single_step(struct task_struct *task) | ||
| 66 | { | ||
| 67 | struct pt_regs *regs = task->thread.regs; | ||
| 68 | if (regs != NULL) | ||
| 69 | regs->msr &= ~MSR_SE; | ||
| 70 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | ||
| 71 | } | ||
| 72 | |||
| 73 | #ifdef CONFIG_ALTIVEC | ||
| 74 | /* | ||
| 75 | * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||
| 76 | * The transfer totals 34 quadword. Quadwords 0-31 contain the | ||
| 77 | * corresponding vector registers. Quadword 32 contains the vscr as the | ||
| 78 | * last word (offset 12) within that quadword. Quadword 33 contains the | ||
| 79 | * vrsave as the first word (offset 0) within the quadword. | ||
| 80 | * | ||
| 81 | * This definition of the VMX state is compatible with the current PPC32 | ||
| 82 | * ptrace interface. This allows signal handling and ptrace to use the | ||
| 83 | * same structures. This also simplifies the implementation of a bi-arch | ||
| 84 | * (combined (32- and 64-bit) gdb. | ||
| 85 | */ | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Get contents of AltiVec register state in task TASK | ||
| 89 | */ | ||
| 90 | static inline int get_vrregs(unsigned long __user *data, | ||
| 91 | struct task_struct *task) | ||
| 92 | { | ||
| 93 | unsigned long regsize; | ||
| 94 | |||
| 95 | /* copy AltiVec registers VR[0] .. VR[31] */ | ||
| 96 | regsize = 32 * sizeof(vector128); | ||
| 97 | if (copy_to_user(data, task->thread.vr, regsize)) | ||
| 98 | return -EFAULT; | ||
| 99 | data += (regsize / sizeof(unsigned long)); | ||
| 100 | |||
| 101 | /* copy VSCR */ | ||
| 102 | regsize = 1 * sizeof(vector128); | ||
| 103 | if (copy_to_user(data, &task->thread.vscr, regsize)) | ||
| 104 | return -EFAULT; | ||
| 105 | data += (regsize / sizeof(unsigned long)); | ||
| 106 | |||
| 107 | /* copy VRSAVE */ | ||
| 108 | if (put_user(task->thread.vrsave, (u32 __user *)data)) | ||
| 109 | return -EFAULT; | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Write contents of AltiVec register state into task TASK. | ||
| 116 | */ | ||
| 117 | static inline int set_vrregs(struct task_struct *task, | ||
| 118 | unsigned long __user *data) | ||
| 119 | { | ||
| 120 | unsigned long regsize; | ||
| 121 | |||
| 122 | /* copy AltiVec registers VR[0] .. VR[31] */ | ||
| 123 | regsize = 32 * sizeof(vector128); | ||
| 124 | if (copy_from_user(task->thread.vr, data, regsize)) | ||
| 125 | return -EFAULT; | ||
| 126 | data += (regsize / sizeof(unsigned long)); | ||
| 127 | |||
| 128 | /* copy VSCR */ | ||
| 129 | regsize = 1 * sizeof(vector128); | ||
| 130 | if (copy_from_user(&task->thread.vscr, data, regsize)) | ||
| 131 | return -EFAULT; | ||
| 132 | data += (regsize / sizeof(unsigned long)); | ||
| 133 | |||
| 134 | /* copy VRSAVE */ | ||
| 135 | if (get_user(task->thread.vrsave, (u32 __user *)data)) | ||
| 136 | return -EFAULT; | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | #endif | ||
| 141 | |||
| 142 | static inline int ptrace_set_debugreg(struct task_struct *task, | ||
| 143 | unsigned long addr, unsigned long data) | ||
| 144 | { | ||
| 145 | /* We only support one DABR and no IABRS at the moment */ | ||
| 146 | if (addr > 0) | ||
| 147 | return -EINVAL; | ||
| 148 | |||
| 149 | /* The bottom 3 bits are flags */ | ||
| 150 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
| 151 | return -EIO; | ||
| 152 | |||
| 153 | /* Ensure translation is on */ | ||
| 154 | if (data && !(data & DABR_TRANSLATION)) | ||
| 155 | return -EIO; | ||
| 156 | |||
| 157 | task->thread.dabr = data; | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | #endif /* _PPC64_PTRACE_COMMON_H */ | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index bf76562167c3..0fb53950da43 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -35,11 +35,11 @@ | |||
| 35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
| 36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
| 37 | 37 | ||
| 38 | #ifdef CONFIG_PPC64 | 38 | /* |
| 39 | #include "ptrace-common.h" | 39 | * does not yet catch signals sent when the child dies. |
| 40 | #endif | 40 | * in exit.c or in signal.c. |
| 41 | */ | ||
| 41 | 42 | ||
| 42 | #ifdef CONFIG_PPC32 | ||
| 43 | /* | 43 | /* |
| 44 | * Set of msr bits that gdb can change on behalf of a process. | 44 | * Set of msr bits that gdb can change on behalf of a process. |
| 45 | */ | 45 | */ |
| @@ -48,65 +48,117 @@ | |||
| 48 | #else | 48 | #else |
| 49 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) | 49 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) |
| 50 | #endif | 50 | #endif |
| 51 | #endif /* CONFIG_PPC32 */ | ||
| 52 | 51 | ||
| 53 | /* | 52 | /* |
| 54 | * does not yet catch signals sent when the child dies. | 53 | * Max register writeable via put_reg |
| 55 | * in exit.c or in signal.c. | ||
| 56 | */ | 54 | */ |
| 57 | |||
| 58 | #ifdef CONFIG_PPC32 | 55 | #ifdef CONFIG_PPC32 |
| 56 | #define PT_MAX_PUT_REG PT_MQ | ||
| 57 | #else | ||
| 58 | #define PT_MAX_PUT_REG PT_CCR | ||
| 59 | #endif | ||
| 60 | |||
| 59 | /* | 61 | /* |
| 60 | * Get contents of register REGNO in task TASK. | 62 | * Get contents of register REGNO in task TASK. |
| 61 | */ | 63 | */ |
| 62 | static inline unsigned long get_reg(struct task_struct *task, int regno) | 64 | unsigned long ptrace_get_reg(struct task_struct *task, int regno) |
| 63 | { | 65 | { |
| 64 | if (regno < sizeof(struct pt_regs) / sizeof(unsigned long) | 66 | unsigned long tmp = 0; |
| 65 | && task->thread.regs != NULL) | 67 | |
| 68 | if (task->thread.regs == NULL) | ||
| 69 | return -EIO; | ||
| 70 | |||
| 71 | if (regno == PT_MSR) { | ||
| 72 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||
| 73 | return tmp | task->thread.fpexc_mode; | ||
| 74 | } | ||
| 75 | |||
| 76 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | ||
| 66 | return ((unsigned long *)task->thread.regs)[regno]; | 77 | return ((unsigned long *)task->thread.regs)[regno]; |
| 67 | return (0); | 78 | |
| 79 | return -EIO; | ||
| 68 | } | 80 | } |
| 69 | 81 | ||
| 70 | /* | 82 | /* |
| 71 | * Write contents of register REGNO in task TASK. | 83 | * Write contents of register REGNO in task TASK. |
| 72 | */ | 84 | */ |
| 73 | static inline int put_reg(struct task_struct *task, int regno, | 85 | int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) |
| 74 | unsigned long data) | ||
| 75 | { | 86 | { |
| 76 | if (regno <= PT_MQ && task->thread.regs != NULL) { | 87 | if (task->thread.regs == NULL) |
| 88 | return -EIO; | ||
| 89 | |||
| 90 | if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { | ||
| 77 | if (regno == PT_MSR) | 91 | if (regno == PT_MSR) |
| 78 | data = (data & MSR_DEBUGCHANGE) | 92 | data = (data & MSR_DEBUGCHANGE) |
| 79 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | 93 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); |
| 94 | /* We prevent mucking around with the reserved area of trap | ||
| 95 | * which are used internally by the kernel | ||
| 96 | */ | ||
| 97 | if (regno == PT_TRAP) | ||
| 98 | data &= 0xfff0; | ||
| 80 | ((unsigned long *)task->thread.regs)[regno] = data; | 99 | ((unsigned long *)task->thread.regs)[regno] = data; |
| 81 | return 0; | 100 | return 0; |
| 82 | } | 101 | } |
| 83 | return -EIO; | 102 | return -EIO; |
| 84 | } | 103 | } |
| 85 | 104 | ||
| 105 | |||
| 106 | static int get_fpregs(void __user *data, struct task_struct *task, | ||
| 107 | int has_fpscr) | ||
| 108 | { | ||
| 109 | unsigned int count = has_fpscr ? 33 : 32; | ||
| 110 | |||
| 111 | if (copy_to_user(data, task->thread.fpr, count * sizeof(double))) | ||
| 112 | return -EFAULT; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int set_fpregs(void __user *data, struct task_struct *task, | ||
| 117 | int has_fpscr) | ||
| 118 | { | ||
| 119 | unsigned int count = has_fpscr ? 33 : 32; | ||
| 120 | |||
| 121 | if (copy_from_user(task->thread.fpr, data, count * sizeof(double))) | ||
| 122 | return -EFAULT; | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | |||
| 86 | #ifdef CONFIG_ALTIVEC | 127 | #ifdef CONFIG_ALTIVEC |
| 87 | /* | 128 | /* |
| 129 | * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||
| 130 | * The transfer totals 34 quadword. Quadwords 0-31 contain the | ||
| 131 | * corresponding vector registers. Quadword 32 contains the vscr as the | ||
| 132 | * last word (offset 12) within that quadword. Quadword 33 contains the | ||
| 133 | * vrsave as the first word (offset 0) within the quadword. | ||
| 134 | * | ||
| 135 | * This definition of the VMX state is compatible with the current PPC32 | ||
| 136 | * ptrace interface. This allows signal handling and ptrace to use the | ||
| 137 | * same structures. This also simplifies the implementation of a bi-arch | ||
| 138 | * (combined (32- and 64-bit) gdb. | ||
| 139 | */ | ||
| 140 | |||
| 141 | /* | ||
| 88 | * Get contents of AltiVec register state in task TASK | 142 | * Get contents of AltiVec register state in task TASK |
| 89 | */ | 143 | */ |
| 90 | static inline int get_vrregs(unsigned long __user *data, struct task_struct *task) | 144 | static int get_vrregs(unsigned long __user *data, struct task_struct *task) |
| 91 | { | 145 | { |
| 92 | int i, j; | 146 | unsigned long regsize; |
| 93 | |||
| 94 | if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long))) | ||
| 95 | return -EFAULT; | ||
| 96 | 147 | ||
| 97 | /* copy AltiVec registers VR[0] .. VR[31] */ | 148 | /* copy AltiVec registers VR[0] .. VR[31] */ |
| 98 | for (i = 0; i < 32; i++) | 149 | regsize = 32 * sizeof(vector128); |
| 99 | for (j = 0; j < 4; j++, data++) | 150 | if (copy_to_user(data, task->thread.vr, regsize)) |
| 100 | if (__put_user(task->thread.vr[i].u[j], data)) | 151 | return -EFAULT; |
| 101 | return -EFAULT; | 152 | data += (regsize / sizeof(unsigned long)); |
| 102 | 153 | ||
| 103 | /* copy VSCR */ | 154 | /* copy VSCR */ |
| 104 | for (i = 0; i < 4; i++, data++) | 155 | regsize = 1 * sizeof(vector128); |
| 105 | if (__put_user(task->thread.vscr.u[i], data)) | 156 | if (copy_to_user(data, &task->thread.vscr, regsize)) |
| 106 | return -EFAULT; | 157 | return -EFAULT; |
| 158 | data += (regsize / sizeof(unsigned long)); | ||
| 107 | 159 | ||
| 108 | /* copy VRSAVE */ | 160 | /* copy VRSAVE */ |
| 109 | if (__put_user(task->thread.vrsave, data)) | 161 | if (put_user(task->thread.vrsave, (u32 __user *)data)) |
| 110 | return -EFAULT; | 162 | return -EFAULT; |
| 111 | 163 | ||
| 112 | return 0; | 164 | return 0; |
| @@ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas | |||
| 115 | /* | 167 | /* |
| 116 | * Write contents of AltiVec register state into task TASK. | 168 | * Write contents of AltiVec register state into task TASK. |
| 117 | */ | 169 | */ |
| 118 | static inline int set_vrregs(struct task_struct *task, unsigned long __user *data) | 170 | static int set_vrregs(struct task_struct *task, unsigned long __user *data) |
| 119 | { | 171 | { |
| 120 | int i, j; | 172 | unsigned long regsize; |
| 121 | |||
| 122 | if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long))) | ||
| 123 | return -EFAULT; | ||
| 124 | 173 | ||
| 125 | /* copy AltiVec registers VR[0] .. VR[31] */ | 174 | /* copy AltiVec registers VR[0] .. VR[31] */ |
| 126 | for (i = 0; i < 32; i++) | 175 | regsize = 32 * sizeof(vector128); |
| 127 | for (j = 0; j < 4; j++, data++) | 176 | if (copy_from_user(task->thread.vr, data, regsize)) |
| 128 | if (__get_user(task->thread.vr[i].u[j], data)) | 177 | return -EFAULT; |
| 129 | return -EFAULT; | 178 | data += (regsize / sizeof(unsigned long)); |
| 130 | 179 | ||
| 131 | /* copy VSCR */ | 180 | /* copy VSCR */ |
| 132 | for (i = 0; i < 4; i++, data++) | 181 | regsize = 1 * sizeof(vector128); |
| 133 | if (__get_user(task->thread.vscr.u[i], data)) | 182 | if (copy_from_user(&task->thread.vscr, data, regsize)) |
| 134 | return -EFAULT; | 183 | return -EFAULT; |
| 184 | data += (regsize / sizeof(unsigned long)); | ||
| 135 | 185 | ||
| 136 | /* copy VRSAVE */ | 186 | /* copy VRSAVE */ |
| 137 | if (__get_user(task->thread.vrsave, data)) | 187 | if (get_user(task->thread.vrsave, (u32 __user *)data)) |
| 138 | return -EFAULT; | 188 | return -EFAULT; |
| 139 | 189 | ||
| 140 | return 0; | 190 | return 0; |
| 141 | } | 191 | } |
| 142 | #endif | 192 | #endif /* CONFIG_ALTIVEC */ |
| 143 | 193 | ||
| 144 | #ifdef CONFIG_SPE | 194 | #ifdef CONFIG_SPE |
| 145 | 195 | ||
| @@ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat | |||
| 156 | /* | 206 | /* |
| 157 | * Get contents of SPE register state in task TASK. | 207 | * Get contents of SPE register state in task TASK. |
| 158 | */ | 208 | */ |
| 159 | static inline int get_evrregs(unsigned long *data, struct task_struct *task) | 209 | static int get_evrregs(unsigned long *data, struct task_struct *task) |
| 160 | { | 210 | { |
| 161 | int i; | 211 | int i; |
| 162 | 212 | ||
| @@ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task) | |||
| 182 | /* | 232 | /* |
| 183 | * Write contents of SPE register state into task TASK. | 233 | * Write contents of SPE register state into task TASK. |
| 184 | */ | 234 | */ |
| 185 | static inline int set_evrregs(struct task_struct *task, unsigned long *data) | 235 | static int set_evrregs(struct task_struct *task, unsigned long *data) |
| 186 | { | 236 | { |
| 187 | int i; | 237 | int i; |
| 188 | 238 | ||
| @@ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data) | |||
| 205 | } | 255 | } |
| 206 | #endif /* CONFIG_SPE */ | 256 | #endif /* CONFIG_SPE */ |
| 207 | 257 | ||
| 208 | static inline void | 258 | |
| 209 | set_single_step(struct task_struct *task) | 259 | static void set_single_step(struct task_struct *task) |
| 210 | { | 260 | { |
| 211 | struct pt_regs *regs = task->thread.regs; | 261 | struct pt_regs *regs = task->thread.regs; |
| 212 | 262 | ||
| @@ -221,8 +271,7 @@ set_single_step(struct task_struct *task) | |||
| 221 | set_tsk_thread_flag(task, TIF_SINGLESTEP); | 271 | set_tsk_thread_flag(task, TIF_SINGLESTEP); |
| 222 | } | 272 | } |
| 223 | 273 | ||
| 224 | static inline void | 274 | static void clear_single_step(struct task_struct *task) |
| 225 | clear_single_step(struct task_struct *task) | ||
| 226 | { | 275 | { |
| 227 | struct pt_regs *regs = task->thread.regs; | 276 | struct pt_regs *regs = task->thread.regs; |
| 228 | 277 | ||
| @@ -236,7 +285,25 @@ clear_single_step(struct task_struct *task) | |||
| 236 | } | 285 | } |
| 237 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 286 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
| 238 | } | 287 | } |
| 239 | #endif /* CONFIG_PPC32 */ | 288 | |
| 289 | static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | ||
| 290 | unsigned long data) | ||
| 291 | { | ||
| 292 | /* We only support one DABR and no IABRS at the moment */ | ||
| 293 | if (addr > 0) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 296 | /* The bottom 3 bits are flags */ | ||
| 297 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
| 298 | return -EIO; | ||
| 299 | |||
| 300 | /* Ensure translation is on */ | ||
| 301 | if (data && !(data & DABR_TRANSLATION)) | ||
| 302 | return -EIO; | ||
| 303 | |||
| 304 | task->thread.dabr = data; | ||
| 305 | return 0; | ||
| 306 | } | ||
| 240 | 307 | ||
| 241 | /* | 308 | /* |
| 242 | * Called by kernel/ptrace.c when detaching.. | 309 | * Called by kernel/ptrace.c when detaching.. |
| @@ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child) | |||
| 249 | clear_single_step(child); | 316 | clear_single_step(child); |
| 250 | } | 317 | } |
| 251 | 318 | ||
| 319 | /* | ||
| 320 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||
| 321 | * we mark them as obsolete now, they will be removed in a future version | ||
| 322 | */ | ||
| 323 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, | ||
| 324 | long data) | ||
| 325 | { | ||
| 326 | int ret = -EPERM; | ||
| 327 | |||
| 328 | switch(request) { | ||
| 329 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||
| 330 | int i; | ||
| 331 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 332 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
| 333 | |||
| 334 | for (i = 0; i < 32; i++) { | ||
| 335 | ret = put_user(*reg, tmp); | ||
| 336 | if (ret) | ||
| 337 | break; | ||
| 338 | reg++; | ||
| 339 | tmp++; | ||
| 340 | } | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | |||
| 344 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
| 345 | int i; | ||
| 346 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 347 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
| 348 | |||
| 349 | for (i = 0; i < 32; i++) { | ||
| 350 | ret = get_user(*reg, tmp); | ||
| 351 | if (ret) | ||
| 352 | break; | ||
| 353 | reg++; | ||
| 354 | tmp++; | ||
| 355 | } | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | |||
| 359 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||
| 360 | flush_fp_to_thread(child); | ||
| 361 | ret = get_fpregs((void __user *)addr, child, 0); | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | |||
| 365 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
| 366 | flush_fp_to_thread(child); | ||
| 367 | ret = set_fpregs((void __user *)addr, child, 0); | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | |||
| 371 | } | ||
| 372 | return ret; | ||
| 373 | } | ||
| 374 | |||
| 252 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 375 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 253 | { | 376 | { |
| 254 | int ret = -EPERM; | 377 | int ret = -EPERM; |
| @@ -284,11 +407,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 284 | #endif | 407 | #endif |
| 285 | break; | 408 | break; |
| 286 | 409 | ||
| 287 | #ifdef CONFIG_PPC32 | ||
| 288 | CHECK_FULL_REGS(child->thread.regs); | 410 | CHECK_FULL_REGS(child->thread.regs); |
| 289 | #endif | ||
| 290 | if (index < PT_FPR0) { | 411 | if (index < PT_FPR0) { |
| 291 | tmp = get_reg(child, (int) index); | 412 | tmp = ptrace_get_reg(child, (int) index); |
| 292 | } else { | 413 | } else { |
| 293 | flush_fp_to_thread(child); | 414 | flush_fp_to_thread(child); |
| 294 | tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; | 415 | tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; |
| @@ -323,13 +444,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 323 | #endif | 444 | #endif |
| 324 | break; | 445 | break; |
| 325 | 446 | ||
| 326 | #ifdef CONFIG_PPC32 | ||
| 327 | CHECK_FULL_REGS(child->thread.regs); | 447 | CHECK_FULL_REGS(child->thread.regs); |
| 328 | #endif | ||
| 329 | if (index == PT_ORIG_R3) | ||
| 330 | break; | ||
| 331 | if (index < PT_FPR0) { | 448 | if (index < PT_FPR0) { |
| 332 | ret = put_reg(child, index, data); | 449 | ret = ptrace_put_reg(child, index, data); |
| 333 | } else { | 450 | } else { |
| 334 | flush_fp_to_thread(child); | 451 | flush_fp_to_thread(child); |
| 335 | ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; | 452 | ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; |
| @@ -384,7 +501,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 384 | break; | 501 | break; |
| 385 | } | 502 | } |
| 386 | 503 | ||
| 387 | #ifdef CONFIG_PPC64 | ||
| 388 | case PTRACE_GET_DEBUGREG: { | 504 | case PTRACE_GET_DEBUGREG: { |
| 389 | ret = -EINVAL; | 505 | ret = -EINVAL; |
| 390 | /* We only support one DABR and no IABRS at the moment */ | 506 | /* We only support one DABR and no IABRS at the moment */ |
| @@ -398,73 +514,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 398 | case PTRACE_SET_DEBUGREG: | 514 | case PTRACE_SET_DEBUGREG: |
| 399 | ret = ptrace_set_debugreg(child, addr, data); | 515 | ret = ptrace_set_debugreg(child, addr, data); |
| 400 | break; | 516 | break; |
| 401 | #endif | ||
| 402 | 517 | ||
| 403 | case PTRACE_DETACH: | 518 | case PTRACE_DETACH: |
| 404 | ret = ptrace_detach(child, data); | 519 | ret = ptrace_detach(child, data); |
| 405 | break; | 520 | break; |
| 406 | 521 | ||
| 407 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 522 | #ifdef CONFIG_PPC64 |
| 408 | int i; | 523 | case PTRACE_GETREGS64: |
| 409 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 524 | #endif |
| 410 | unsigned long __user *tmp = (unsigned long __user *)addr; | 525 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ |
| 411 | 526 | int ui; | |
| 412 | for (i = 0; i < 32; i++) { | 527 | if (!access_ok(VERIFY_WRITE, (void __user *)data, |
| 413 | ret = put_user(*reg, tmp); | 528 | sizeof(struct pt_regs))) { |
| 414 | if (ret) | 529 | ret = -EIO; |
| 415 | break; | 530 | break; |
| 416 | reg++; | 531 | } |
| 417 | tmp++; | 532 | ret = 0; |
| 533 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
| 534 | ret |= __put_user(ptrace_get_reg(child, ui), | ||
| 535 | (unsigned long __user *) data); | ||
| 536 | data += sizeof(long); | ||
| 418 | } | 537 | } |
| 419 | break; | 538 | break; |
| 420 | } | 539 | } |
| 421 | 540 | ||
| 422 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 541 | #ifdef CONFIG_PPC64 |
| 423 | int i; | 542 | case PTRACE_SETREGS64: |
| 424 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 543 | #endif |
| 425 | unsigned long __user *tmp = (unsigned long __user *)addr; | 544 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
| 426 | 545 | unsigned long tmp; | |
| 427 | for (i = 0; i < 32; i++) { | 546 | int ui; |
| 428 | ret = get_user(*reg, tmp); | 547 | if (!access_ok(VERIFY_READ, (void __user *)data, |
| 548 | sizeof(struct pt_regs))) { | ||
| 549 | ret = -EIO; | ||
| 550 | break; | ||
| 551 | } | ||
| 552 | ret = 0; | ||
| 553 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
| 554 | ret = __get_user(tmp, (unsigned long __user *) data); | ||
| 429 | if (ret) | 555 | if (ret) |
| 430 | break; | 556 | break; |
| 431 | reg++; | 557 | ptrace_put_reg(child, ui, tmp); |
| 432 | tmp++; | 558 | data += sizeof(long); |
| 433 | } | 559 | } |
| 434 | break; | 560 | break; |
| 435 | } | 561 | } |
| 436 | 562 | ||
| 437 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | 563 | case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ |
| 438 | int i; | ||
| 439 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
| 440 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
| 441 | |||
| 442 | flush_fp_to_thread(child); | 564 | flush_fp_to_thread(child); |
| 443 | 565 | ret = get_fpregs((void __user *)data, child, 1); | |
| 444 | for (i = 0; i < 32; i++) { | ||
| 445 | ret = put_user(*reg, tmp); | ||
| 446 | if (ret) | ||
| 447 | break; | ||
| 448 | reg++; | ||
| 449 | tmp++; | ||
| 450 | } | ||
| 451 | break; | 566 | break; |
| 452 | } | 567 | } |
| 453 | 568 | ||
| 454 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | 569 | case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ |
| 455 | int i; | ||
| 456 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
| 457 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
| 458 | |||
| 459 | flush_fp_to_thread(child); | 570 | flush_fp_to_thread(child); |
| 460 | 571 | ret = set_fpregs((void __user *)data, child, 1); | |
| 461 | for (i = 0; i < 32; i++) { | ||
| 462 | ret = get_user(*reg, tmp); | ||
| 463 | if (ret) | ||
| 464 | break; | ||
| 465 | reg++; | ||
| 466 | tmp++; | ||
| 467 | } | ||
| 468 | break; | 572 | break; |
| 469 | } | 573 | } |
| 470 | 574 | ||
| @@ -499,11 +603,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 499 | break; | 603 | break; |
| 500 | #endif | 604 | #endif |
| 501 | 605 | ||
| 606 | /* Old reverse args ptrace callss */ | ||
| 607 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | ||
| 608 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | ||
| 609 | case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ | ||
| 610 | case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */ | ||
| 611 | ret = arch_ptrace_old(child, request, addr, data); | ||
| 612 | break; | ||
| 613 | |||
| 502 | default: | 614 | default: |
| 503 | ret = ptrace_request(child, request, addr, data); | 615 | ret = ptrace_request(child, request, addr, data); |
| 504 | break; | 616 | break; |
| 505 | } | 617 | } |
| 506 | |||
| 507 | return ret; | 618 | return ret; |
| 508 | } | 619 | } |
| 509 | 620 | ||
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 9b9a230349bc..9e6baeac0fb1 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
| @@ -33,13 +33,55 @@ | |||
| 33 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
| 34 | #include <asm/system.h> | 34 | #include <asm/system.h> |
| 35 | 35 | ||
| 36 | #include "ptrace-common.h" | ||
| 37 | |||
| 38 | /* | 36 | /* |
| 39 | * does not yet catch signals sent when the child dies. | 37 | * does not yet catch signals sent when the child dies. |
| 40 | * in exit.c or in signal.c. | 38 | * in exit.c or in signal.c. |
| 41 | */ | 39 | */ |
| 42 | 40 | ||
| 41 | /* | ||
| 42 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||
| 43 | * we mark them as obsolete now, they will be removed in a future version | ||
| 44 | */ | ||
| 45 | static long compat_ptrace_old(struct task_struct *child, long request, | ||
| 46 | long addr, long data) | ||
| 47 | { | ||
| 48 | int ret = -EPERM; | ||
| 49 | |||
| 50 | switch(request) { | ||
| 51 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||
| 52 | int i; | ||
| 53 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 54 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
| 55 | |||
| 56 | for (i = 0; i < 32; i++) { | ||
| 57 | ret = put_user(*reg, tmp); | ||
| 58 | if (ret) | ||
| 59 | break; | ||
| 60 | reg++; | ||
| 61 | tmp++; | ||
| 62 | } | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
| 67 | int i; | ||
| 68 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 69 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
| 70 | |||
| 71 | for (i = 0; i < 32; i++) { | ||
| 72 | ret = get_user(*reg, tmp); | ||
| 73 | if (ret) | ||
| 74 | break; | ||
| 75 | reg++; | ||
| 76 | tmp++; | ||
| 77 | } | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | |||
| 81 | } | ||
| 82 | return ret; | ||
| 83 | } | ||
| 84 | |||
| 43 | long compat_sys_ptrace(int request, int pid, unsigned long addr, | 85 | long compat_sys_ptrace(int request, int pid, unsigned long addr, |
| 44 | unsigned long data) | 86 | unsigned long data) |
| 45 | { | 87 | { |
| @@ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 123 | break; | 165 | break; |
| 124 | 166 | ||
| 125 | if (index < PT_FPR0) { | 167 | if (index < PT_FPR0) { |
| 126 | tmp = get_reg(child, index); | 168 | tmp = ptrace_get_reg(child, index); |
| 127 | } else { | 169 | } else { |
| 128 | flush_fp_to_thread(child); | 170 | flush_fp_to_thread(child); |
| 129 | /* | 171 | /* |
| @@ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 162 | else | 204 | else |
| 163 | part = 0; /* want the 1st half of the register (left-most). */ | 205 | part = 0; /* want the 1st half of the register (left-most). */ |
| 164 | 206 | ||
| 165 | /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ | 207 | /* Validate the input - check to see if address is on the wrong boundary |
| 208 | * or beyond the end of the user area | ||
| 209 | */ | ||
| 166 | if ((addr & 3) || numReg > PT_FPSCR) | 210 | if ((addr & 3) || numReg > PT_FPSCR) |
| 167 | break; | 211 | break; |
| 168 | 212 | ||
| @@ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 170 | flush_fp_to_thread(child); | 214 | flush_fp_to_thread(child); |
| 171 | tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; | 215 | tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; |
| 172 | } else { /* register within PT_REGS struct */ | 216 | } else { /* register within PT_REGS struct */ |
| 173 | tmp = get_reg(child, numReg); | 217 | tmp = ptrace_get_reg(child, numReg); |
| 174 | } | 218 | } |
| 175 | reg32bits = ((u32*)&tmp)[part]; | 219 | reg32bits = ((u32*)&tmp)[part]; |
| 176 | ret = put_user(reg32bits, (u32 __user *)data); | 220 | ret = put_user(reg32bits, (u32 __user *)data); |
| @@ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 226 | if ((addr & 3) || (index > PT_FPSCR32)) | 270 | if ((addr & 3) || (index > PT_FPSCR32)) |
| 227 | break; | 271 | break; |
| 228 | 272 | ||
| 229 | if (index == PT_ORIG_R3) | ||
| 230 | break; | ||
| 231 | if (index < PT_FPR0) { | 273 | if (index < PT_FPR0) { |
| 232 | ret = put_reg(child, index, data); | 274 | ret = ptrace_put_reg(child, index, data); |
| 233 | } else { | 275 | } else { |
| 234 | flush_fp_to_thread(child); | 276 | flush_fp_to_thread(child); |
| 235 | /* | 277 | /* |
| @@ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 258 | /* Determine which register the user wants */ | 300 | /* Determine which register the user wants */ |
| 259 | index = (u64)addr >> 2; | 301 | index = (u64)addr >> 2; |
| 260 | numReg = index / 2; | 302 | numReg = index / 2; |
| 303 | |||
| 261 | /* | 304 | /* |
| 262 | * Validate the input - check to see if address is on the | 305 | * Validate the input - check to see if address is on the |
| 263 | * wrong boundary or beyond the end of the user area | 306 | * wrong boundary or beyond the end of the user area |
| 264 | */ | 307 | */ |
| 265 | if ((addr & 3) || (numReg > PT_FPSCR)) | 308 | if ((addr & 3) || (numReg > PT_FPSCR)) |
| 266 | break; | 309 | break; |
| 267 | /* Insure it is a register we let them change */ | 310 | if (numReg < PT_FPR0) { |
| 268 | if ((numReg == PT_ORIG_R3) | 311 | unsigned long freg = ptrace_get_reg(child, numReg); |
| 269 | || ((numReg > PT_CCR) && (numReg < PT_FPR0))) | 312 | if (index % 2) |
| 270 | break; | 313 | freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); |
| 271 | if (numReg >= PT_FPR0) { | 314 | else |
| 315 | freg = (freg & 0xfffffffful) | (data << 32); | ||
| 316 | ret = ptrace_put_reg(child, numReg, freg); | ||
| 317 | } else { | ||
| 272 | flush_fp_to_thread(child); | 318 | flush_fp_to_thread(child); |
| 319 | ((unsigned int *)child->thread.regs)[index] = data; | ||
| 320 | ret = 0; | ||
| 273 | } | 321 | } |
| 274 | if (numReg == PT_MSR) | ||
| 275 | data = (data & MSR_DEBUGCHANGE) | ||
| 276 | | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||
| 277 | ((u32*)child->thread.regs)[index] = data; | ||
| 278 | ret = 0; | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | |||
| 282 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
| 283 | case PTRACE_CONT: { /* restart after signal. */ | ||
| 284 | ret = -EIO; | ||
| 285 | if (!valid_signal(data)) | ||
| 286 | break; | ||
| 287 | if (request == PTRACE_SYSCALL) | ||
| 288 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 289 | else | ||
| 290 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 291 | child->exit_code = data; | ||
| 292 | /* make sure the single step bit is not set. */ | ||
| 293 | clear_single_step(child); | ||
| 294 | wake_up_process(child); | ||
| 295 | ret = 0; | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | |||
| 299 | /* | ||
| 300 | * make the child exit. Best I can do is send it a sigkill. | ||
| 301 | * perhaps it should be put in the status that it wants to | ||
| 302 | * exit. | ||
| 303 | */ | ||
| 304 | case PTRACE_KILL: { | ||
| 305 | ret = 0; | ||
| 306 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
| 307 | break; | ||
| 308 | child->exit_code = SIGKILL; | ||
| 309 | /* make sure the single step bit is not set. */ | ||
| 310 | clear_single_step(child); | ||
| 311 | wake_up_process(child); | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | |||
| 315 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
| 316 | ret = -EIO; | ||
| 317 | if (!valid_signal(data)) | ||
| 318 | break; | ||
| 319 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 320 | set_single_step(child); | ||
| 321 | child->exit_code = data; | ||
| 322 | /* give it a chance to run. */ | ||
| 323 | wake_up_process(child); | ||
| 324 | ret = 0; | ||
| 325 | break; | 322 | break; |
| 326 | } | 323 | } |
| 327 | 324 | ||
| @@ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
| 334 | break; | 331 | break; |
| 335 | } | 332 | } |
| 336 | 333 | ||
| 337 | case PTRACE_SET_DEBUGREG: | 334 | case PTRACE_GETEVENTMSG: |
| 338 | ret = ptrace_set_debugreg(child, addr, data); | 335 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); |
| 339 | break; | ||
| 340 | |||
| 341 | case PTRACE_DETACH: | ||
| 342 | ret = ptrace_detach(child, data); | ||
| 343 | break; | 336 | break; |
| 344 | 337 | ||
| 345 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 338 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ |
| 346 | int i; | 339 | int ui; |
| 347 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 340 | if (!access_ok(VERIFY_WRITE, (void __user *)data, |
| 348 | unsigned int __user *tmp = (unsigned int __user *)addr; | 341 | PT_REGS_COUNT * sizeof(int))) { |
| 349 | 342 | ret = -EIO; | |
| 350 | for (i = 0; i < 32; i++) { | 343 | break; |
| 351 | ret = put_user(*reg, tmp); | ||
| 352 | if (ret) | ||
| 353 | break; | ||
| 354 | reg++; | ||
| 355 | tmp++; | ||
| 356 | } | 344 | } |
| 357 | break; | 345 | ret = 0; |
| 358 | } | 346 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { |
| 359 | 347 | ret |= __put_user(ptrace_get_reg(child, ui), | |
| 360 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 348 | (unsigned int __user *) data); |
| 361 | int i; | 349 | data += sizeof(int); |
| 362 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 363 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
| 364 | |||
| 365 | for (i = 0; i < 32; i++) { | ||
| 366 | ret = get_user(*reg, tmp); | ||
| 367 | if (ret) | ||
| 368 | break; | ||
| 369 | reg++; | ||
| 370 | tmp++; | ||
| 371 | } | 350 | } |
| 372 | break; | 351 | break; |
| 373 | } | 352 | } |
| 374 | 353 | ||
| 375 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | 354 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
| 376 | int i; | 355 | unsigned long tmp; |
| 377 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | 356 | int ui; |
| 378 | unsigned int __user *tmp = (unsigned int __user *)addr; | 357 | if (!access_ok(VERIFY_READ, (void __user *)data, |
| 379 | 358 | PT_REGS_COUNT * sizeof(int))) { | |
| 380 | flush_fp_to_thread(child); | 359 | ret = -EIO; |
| 381 | 360 | break; | |
| 382 | for (i = 0; i < 32; i++) { | ||
| 383 | ret = put_user(*reg, tmp); | ||
| 384 | if (ret) | ||
| 385 | break; | ||
| 386 | reg++; | ||
| 387 | tmp++; | ||
| 388 | } | 361 | } |
| 389 | break; | 362 | ret = 0; |
| 390 | } | 363 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { |
| 391 | 364 | ret = __get_user(tmp, (unsigned int __user *) data); | |
| 392 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
| 393 | int i; | ||
| 394 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
| 395 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
| 396 | |||
| 397 | flush_fp_to_thread(child); | ||
| 398 | |||
| 399 | for (i = 0; i < 32; i++) { | ||
| 400 | ret = get_user(*reg, tmp); | ||
| 401 | if (ret) | 365 | if (ret) |
| 402 | break; | 366 | break; |
| 403 | reg++; | 367 | ptrace_put_reg(child, ui, tmp); |
| 404 | tmp++; | 368 | data += sizeof(int); |
| 405 | } | 369 | } |
| 406 | break; | 370 | break; |
| 407 | } | 371 | } |
| 408 | 372 | ||
| 409 | case PTRACE_GETEVENTMSG: | 373 | case PTRACE_GETFPREGS: |
| 410 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | 374 | case PTRACE_SETFPREGS: |
| 411 | break; | ||
| 412 | |||
| 413 | #ifdef CONFIG_ALTIVEC | ||
| 414 | case PTRACE_GETVRREGS: | 375 | case PTRACE_GETVRREGS: |
| 415 | /* Get the child altivec register state. */ | 376 | case PTRACE_SETVRREGS: |
| 416 | flush_altivec_to_thread(child); | 377 | case PTRACE_GETREGS64: |
| 417 | ret = get_vrregs((unsigned long __user *)data, child); | 378 | case PTRACE_SETREGS64: |
| 379 | case PPC_PTRACE_GETFPREGS: | ||
| 380 | case PPC_PTRACE_SETFPREGS: | ||
| 381 | case PTRACE_KILL: | ||
| 382 | case PTRACE_SINGLESTEP: | ||
| 383 | case PTRACE_DETACH: | ||
| 384 | case PTRACE_SET_DEBUGREG: | ||
| 385 | case PTRACE_SYSCALL: | ||
| 386 | case PTRACE_CONT: | ||
| 387 | ret = arch_ptrace(child, request, addr, data); | ||
| 418 | break; | 388 | break; |
| 419 | 389 | ||
| 420 | case PTRACE_SETVRREGS: | 390 | /* Old reverse args ptrace callss */ |
| 421 | /* Set the child altivec register state. */ | 391 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ |
| 422 | flush_altivec_to_thread(child); | 392 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ |
| 423 | ret = set_vrregs(child, (unsigned long __user *)data); | 393 | ret = compat_ptrace_old(child, request, addr, data); |
| 424 | break; | 394 | break; |
| 425 | #endif | ||
| 426 | 395 | ||
| 427 | default: | 396 | default: |
| 428 | ret = ptrace_request(child, request, addr, data); | 397 | ret = ptrace_request(child, request, addr, data); |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index f2286822be09..a5de6211b97a 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
| @@ -278,10 +278,8 @@ void __init find_and_init_phbs(void) | |||
| 278 | { | 278 | { |
| 279 | struct device_node *node; | 279 | struct device_node *node; |
| 280 | struct pci_controller *phb; | 280 | struct pci_controller *phb; |
| 281 | unsigned int index; | ||
| 282 | struct device_node *root = of_find_node_by_path("/"); | 281 | struct device_node *root = of_find_node_by_path("/"); |
| 283 | 282 | ||
| 284 | index = 0; | ||
| 285 | for (node = of_get_next_child(root, NULL); | 283 | for (node = of_get_next_child(root, NULL); |
| 286 | node != NULL; | 284 | node != NULL; |
| 287 | node = of_get_next_child(root, node)) { | 285 | node = of_get_next_child(root, node)) { |
| @@ -295,8 +293,7 @@ void __init find_and_init_phbs(void) | |||
| 295 | continue; | 293 | continue; |
| 296 | rtas_setup_phb(phb); | 294 | rtas_setup_phb(phb); |
| 297 | pci_process_bridge_OF_ranges(phb, node, 0); | 295 | pci_process_bridge_OF_ranges(phb, node, 0); |
| 298 | pci_setup_phb_io(phb, index == 0); | 296 | isa_bridge_find_early(phb); |
| 299 | index++; | ||
| 300 | } | 297 | } |
| 301 | 298 | ||
| 302 | of_node_put(root); | 299 | of_node_put(root); |
| @@ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | |||
| 335 | return 1; | 332 | return 1; |
| 336 | } | 333 | } |
| 337 | 334 | ||
| 338 | rc = unmap_bus_range(b); | 335 | rc = pcibios_unmap_io_space(b); |
| 339 | if (rc) { | 336 | if (rc) { |
| 340 | printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", | 337 | printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", |
| 341 | __FUNCTION__, b->name); | 338 | __FUNCTION__, b->name); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index ed07a198f8d6..4924c48cb1ff 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/unistd.h> | 32 | #include <linux/unistd.h> |
| 33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
| 34 | #include <linux/serial_8250.h> | 34 | #include <linux/serial_8250.h> |
| 35 | #include <linux/debugfs.h> | ||
| 35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
| 36 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
| 37 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
| @@ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port) | |||
| 486 | 487 | ||
| 487 | switch(base_port) { | 488 | switch(base_port) { |
| 488 | case I8042_DATA_REG: | 489 | case I8042_DATA_REG: |
| 490 | if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303"))) | ||
| 491 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); | ||
| 492 | if (np) { | ||
| 493 | parent = of_get_parent(np); | ||
| 494 | of_node_put(np); | ||
| 495 | np = parent; | ||
| 496 | break; | ||
| 497 | } | ||
| 489 | np = of_find_node_by_type(NULL, "8042"); | 498 | np = of_find_node_by_type(NULL, "8042"); |
| 490 | break; | 499 | break; |
| 491 | case FDC_BASE: /* FDC1 */ | 500 | case FDC_BASE: /* FDC1 */ |
| @@ -571,3 +580,15 @@ static int __init check_cache_coherency(void) | |||
| 571 | 580 | ||
| 572 | late_initcall(check_cache_coherency); | 581 | late_initcall(check_cache_coherency); |
| 573 | #endif /* CONFIG_CHECK_CACHE_COHERENCY */ | 582 | #endif /* CONFIG_CHECK_CACHE_COHERENCY */ |
| 583 | |||
| 584 | #ifdef CONFIG_DEBUG_FS | ||
| 585 | struct dentry *powerpc_debugfs_root; | ||
| 586 | |||
| 587 | static int powerpc_debugfs_init(void) | ||
| 588 | { | ||
| 589 | powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL); | ||
| 590 | |||
| 591 | return powerpc_debugfs_root == NULL; | ||
| 592 | } | ||
| 593 | arch_initcall(powerpc_debugfs_init); | ||
| 594 | #endif | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 35f8f443c14f..7ec6ba56d83d 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
| @@ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p) | |||
| 262 | * Systems with OF can look in the properties on the cpu node(s) | 262 | * Systems with OF can look in the properties on the cpu node(s) |
| 263 | * for a possibly more accurate value. | 263 | * for a possibly more accurate value. |
| 264 | */ | 264 | */ |
| 265 | if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { | 265 | dcache_bsize = cur_cpu_spec->dcache_bsize; |
| 266 | dcache_bsize = cur_cpu_spec->dcache_bsize; | 266 | icache_bsize = cur_cpu_spec->icache_bsize; |
| 267 | icache_bsize = cur_cpu_spec->icache_bsize; | 267 | ucache_bsize = 0; |
| 268 | ucache_bsize = 0; | 268 | if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) |
| 269 | } else | 269 | ucache_bsize = icache_bsize = dcache_bsize; |
| 270 | ucache_bsize = dcache_bsize = icache_bsize | ||
| 271 | = cur_cpu_spec->dcache_bsize; | ||
| 272 | 270 | ||
| 273 | /* reboot on panic */ | 271 | /* reboot on panic */ |
| 274 | panic_timeout = 180; | 272 | panic_timeout = 180; |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6018178708a5..bc43bba05cf8 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -350,13 +350,11 @@ void __init setup_system(void) | |||
| 350 | { | 350 | { |
| 351 | DBG(" -> setup_system()\n"); | 351 | DBG(" -> setup_system()\n"); |
| 352 | 352 | ||
| 353 | /* Apply the CPUs-specific and firmware specific fixups to kernel | 353 | /* Apply CPUs-specific fixups to kernel text (nop out sections |
| 354 | * text (nop out sections not relevant to this CPU or this firmware) | 354 | * not relevant to this CPU) |
| 355 | */ | 355 | */ |
| 356 | do_feature_fixups(cur_cpu_spec->cpu_features, | 356 | do_feature_fixups(cur_cpu_spec->cpu_features, |
| 357 | &__start___ftr_fixup, &__stop___ftr_fixup); | 357 | &__start___ftr_fixup, &__stop___ftr_fixup); |
| 358 | do_feature_fixups(powerpc_firmware_features, | ||
| 359 | &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | ||
| 360 | 358 | ||
| 361 | /* | 359 | /* |
| 362 | * Unflatten the device-tree passed by prom_init or kexec | 360 | * Unflatten the device-tree passed by prom_init or kexec |
| @@ -394,6 +392,12 @@ void __init setup_system(void) | |||
| 394 | if (ppc_md.init_early) | 392 | if (ppc_md.init_early) |
| 395 | ppc_md.init_early(); | 393 | ppc_md.init_early(); |
| 396 | 394 | ||
| 395 | /* Apply firmware specific fixups to kernel text (nop out | ||
| 396 | * sections not relevant to this firmware) | ||
| 397 | */ | ||
| 398 | do_feature_fixups(powerpc_firmware_features, | ||
| 399 | &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | ||
| 400 | |||
| 397 | /* | 401 | /* |
| 398 | * We can discover serial ports now since the above did setup the | 402 | * We can discover serial ports now since the above did setup the |
| 399 | * hash table management for us, thus ioremap works. We do that early | 403 | * hash table management for us, thus ioremap works. We do that early |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c new file mode 100644 index 000000000000..c434d6c4e4e6 --- /dev/null +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | /* | ||
| 2 | * Common signal handling code for both 32 and 64 bits | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||
| 5 | * Extracted from signal_32.c and signal_64.c | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General | ||
| 8 | * Public License. See the file README.legal in the main directory of | ||
| 9 | * this archive for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/ptrace.h> | ||
| 13 | #include <linux/signal.h> | ||
| 14 | #include <asm/uaccess.h> | ||
| 15 | #include <asm/unistd.h> | ||
| 16 | |||
| 17 | #include "signal.h" | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Allocate space for the signal frame | ||
| 21 | */ | ||
| 22 | void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
| 23 | size_t frame_size) | ||
| 24 | { | ||
| 25 | unsigned long oldsp, newsp; | ||
| 26 | |||
| 27 | /* Default to using normal stack */ | ||
| 28 | oldsp = regs->gpr[1]; | ||
| 29 | |||
| 30 | /* Check for alt stack */ | ||
| 31 | if ((ka->sa.sa_flags & SA_ONSTACK) && | ||
| 32 | current->sas_ss_size && !on_sig_stack(oldsp)) | ||
| 33 | oldsp = (current->sas_ss_sp + current->sas_ss_size); | ||
| 34 | |||
| 35 | /* Get aligned frame */ | ||
| 36 | newsp = (oldsp - frame_size) & ~0xFUL; | ||
| 37 | |||
| 38 | /* Check access */ | ||
| 39 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp)) | ||
| 40 | return NULL; | ||
| 41 | |||
| 42 | return (void __user *)newsp; | ||
| 43 | } | ||
| 44 | |||
| 45 | |||
| 46 | /* | ||
| 47 | * Restore the user process's signal mask | ||
| 48 | */ | ||
| 49 | void restore_sigmask(sigset_t *set) | ||
| 50 | { | ||
| 51 | sigdelsetmask(set, ~_BLOCKABLE); | ||
| 52 | spin_lock_irq(¤t->sighand->siglock); | ||
| 53 | current->blocked = *set; | ||
| 54 | recalc_sigpending(); | ||
| 55 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 56 | } | ||
| 57 | |||
| 58 | static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | ||
| 59 | int has_handler) | ||
| 60 | { | ||
| 61 | unsigned long ret = regs->gpr[3]; | ||
| 62 | int restart = 1; | ||
| 63 | |||
| 64 | /* syscall ? */ | ||
| 65 | if (TRAP(regs) != 0x0C00) | ||
| 66 | return; | ||
| 67 | |||
| 68 | /* error signalled ? */ | ||
| 69 | if (!(regs->ccr & 0x10000000)) | ||
| 70 | return; | ||
| 71 | |||
| 72 | switch (ret) { | ||
| 73 | case ERESTART_RESTARTBLOCK: | ||
| 74 | case ERESTARTNOHAND: | ||
| 75 | /* ERESTARTNOHAND means that the syscall should only be | ||
| 76 | * restarted if there was no handler for the signal, and since | ||
| 77 | * we only get here if there is a handler, we dont restart. | ||
| 78 | */ | ||
| 79 | restart = !has_handler; | ||
| 80 | break; | ||
| 81 | case ERESTARTSYS: | ||
| 82 | /* ERESTARTSYS means to restart the syscall if there is no | ||
| 83 | * handler or the handler was registered with SA_RESTART | ||
| 84 | */ | ||
| 85 | restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0; | ||
| 86 | break; | ||
| 87 | case ERESTARTNOINTR: | ||
| 88 | /* ERESTARTNOINTR means that the syscall should be | ||
| 89 | * called again after the signal handler returns. | ||
| 90 | */ | ||
| 91 | break; | ||
| 92 | default: | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | if (restart) { | ||
| 96 | if (ret == ERESTART_RESTARTBLOCK) | ||
| 97 | regs->gpr[0] = __NR_restart_syscall; | ||
| 98 | else | ||
| 99 | regs->gpr[3] = regs->orig_gpr3; | ||
| 100 | regs->nip -= 4; | ||
| 101 | regs->result = 0; | ||
| 102 | } else { | ||
| 103 | regs->result = -EINTR; | ||
| 104 | regs->gpr[3] = EINTR; | ||
| 105 | regs->ccr |= 0x10000000; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
| 110 | { | ||
| 111 | siginfo_t info; | ||
| 112 | int signr; | ||
| 113 | struct k_sigaction ka; | ||
| 114 | int ret; | ||
| 115 | int is32 = is_32bit_task(); | ||
| 116 | |||
| 117 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 118 | oldset = ¤t->saved_sigmask; | ||
| 119 | else if (!oldset) | ||
| 120 | oldset = ¤t->blocked; | ||
| 121 | |||
| 122 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
| 123 | |||
| 124 | /* Is there any syscall restart business here ? */ | ||
| 125 | check_syscall_restart(regs, &ka, signr > 0); | ||
| 126 | |||
| 127 | if (signr <= 0) { | ||
| 128 | /* No signal to deliver -- put the saved sigmask back */ | ||
| 129 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 130 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 131 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 132 | } | ||
| 133 | return 0; /* no signals delivered */ | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Reenable the DABR before delivering the signal to | ||
| 138 | * user space. The DABR will have been cleared if it | ||
| 139 | * triggered inside the kernel. | ||
| 140 | */ | ||
| 141 | if (current->thread.dabr) | ||
| 142 | set_dabr(current->thread.dabr); | ||
| 143 | |||
| 144 | if (is32) { | ||
| 145 | if (ka.sa.sa_flags & SA_SIGINFO) | ||
| 146 | ret = handle_rt_signal32(signr, &ka, &info, oldset, | ||
| 147 | regs); | ||
| 148 | else | ||
| 149 | ret = handle_signal32(signr, &ka, &info, oldset, | ||
| 150 | regs); | ||
| 151 | } else { | ||
| 152 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); | ||
| 153 | } | ||
| 154 | |||
| 155 | if (ret) { | ||
| 156 | spin_lock_irq(¤t->sighand->siglock); | ||
| 157 | sigorsets(¤t->blocked, ¤t->blocked, | ||
| 158 | &ka.sa.sa_mask); | ||
| 159 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
| 160 | sigaddset(¤t->blocked, signr); | ||
| 161 | recalc_sigpending(); | ||
| 162 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 163 | |||
| 164 | /* | ||
| 165 | * A signal was successfully delivered; the saved sigmask is in | ||
| 166 | * its frame, and we can clear the TIF_RESTORE_SIGMASK flag. | ||
| 167 | */ | ||
| 168 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 169 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 170 | } | ||
| 171 | |||
| 172 | return ret; | ||
| 173 | } | ||
| 174 | |||
| 175 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
| 176 | unsigned long r5, unsigned long r6, unsigned long r7, | ||
| 177 | unsigned long r8, struct pt_regs *regs) | ||
| 178 | { | ||
| 179 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
| 180 | } | ||
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h new file mode 100644 index 000000000000..77efb3d5465a --- /dev/null +++ b/arch/powerpc/kernel/signal.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||
| 3 | * Extracted from signal_32.c and signal_64.c | ||
| 4 | * | ||
| 5 | * This file is subject to the terms and conditions of the GNU General | ||
| 6 | * Public License. See the file README.legal in the main directory of | ||
| 7 | * this archive for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _POWERPC_ARCH_SIGNAL_H | ||
| 11 | #define _POWERPC_ARCH_SIGNAL_H | ||
| 12 | |||
| 13 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
| 14 | |||
| 15 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
| 16 | size_t frame_size); | ||
| 17 | extern void restore_sigmask(sigset_t *set); | ||
| 18 | |||
| 19 | extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, | ||
| 20 | siginfo_t *info, sigset_t *oldset, | ||
| 21 | struct pt_regs *regs); | ||
| 22 | |||
| 23 | extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | ||
| 24 | siginfo_t *info, sigset_t *oldset, | ||
| 25 | struct pt_regs *regs); | ||
| 26 | |||
| 27 | |||
| 28 | #ifdef CONFIG_PPC64 | ||
| 29 | |||
| 30 | static inline int is_32bit_task(void) | ||
| 31 | { | ||
| 32 | return test_thread_flag(TIF_32BIT); | ||
| 33 | } | ||
| 34 | |||
| 35 | extern int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||
| 36 | siginfo_t *info, sigset_t *set, | ||
| 37 | struct pt_regs *regs); | ||
| 38 | |||
| 39 | #else /* CONFIG_PPC64 */ | ||
| 40 | |||
| 41 | static inline int is_32bit_task(void) | ||
| 42 | { | ||
| 43 | return 1; | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||
| 47 | siginfo_t *info, sigset_t *set, | ||
| 48 | struct pt_regs *regs) | ||
| 49 | { | ||
| 50 | return -EFAULT; | ||
| 51 | } | ||
| 52 | |||
| 53 | #endif /* !defined(CONFIG_PPC64) */ | ||
| 54 | |||
| 55 | #endif /* _POWERPC_ARCH_SIGNAL_H */ | ||
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index dd1dca5bfa81..590057e9e987 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -51,12 +51,11 @@ | |||
| 51 | #include <asm/pgtable.h> | 51 | #include <asm/pgtable.h> |
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| 54 | #undef DEBUG_SIG | 54 | #include "signal.h" |
| 55 | 55 | ||
| 56 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 56 | #undef DEBUG_SIG |
| 57 | 57 | ||
| 58 | #ifdef CONFIG_PPC64 | 58 | #ifdef CONFIG_PPC64 |
| 59 | #define do_signal do_signal32 | ||
| 60 | #define sys_sigsuspend compat_sys_sigsuspend | 59 | #define sys_sigsuspend compat_sys_sigsuspend |
| 61 | #define sys_rt_sigsuspend compat_sys_rt_sigsuspend | 60 | #define sys_rt_sigsuspend compat_sys_rt_sigsuspend |
| 62 | #define sys_rt_sigreturn compat_sys_rt_sigreturn | 61 | #define sys_rt_sigreturn compat_sys_rt_sigreturn |
| @@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs, | |||
| 231 | 230 | ||
| 232 | #endif /* CONFIG_PPC64 */ | 231 | #endif /* CONFIG_PPC64 */ |
| 233 | 232 | ||
| 234 | int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
| 235 | |||
| 236 | /* | 233 | /* |
| 237 | * Atomically swap in the new signal mask, and wait for a signal. | 234 | * Atomically swap in the new signal mask, and wait for a signal. |
| 238 | */ | 235 | */ |
| @@ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask) | |||
| 251 | return -ERESTARTNOHAND; | 248 | return -ERESTARTNOHAND; |
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | #ifdef CONFIG_PPC32 | ||
| 255 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5, | ||
| 256 | int r6, int r7, int r8, struct pt_regs *regs) | ||
| 257 | { | ||
| 258 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
| 259 | } | ||
| 260 | #endif | ||
| 261 | |||
| 262 | long sys_sigaction(int sig, struct old_sigaction __user *act, | 251 | long sys_sigaction(int sig, struct old_sigaction __user *act, |
| 263 | struct old_sigaction __user *oact) | 252 | struct old_sigaction __user *oact) |
| 264 | { | 253 | { |
| @@ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, | |||
| 293 | /* | 282 | /* |
| 294 | * When we have signals to deliver, we set up on the | 283 | * When we have signals to deliver, we set up on the |
| 295 | * user stack, going down from the original stack pointer: | 284 | * user stack, going down from the original stack pointer: |
| 296 | * a sigregs struct | 285 | * an ABI gap of 56 words |
| 286 | * an mcontext struct | ||
| 297 | * a sigcontext struct | 287 | * a sigcontext struct |
| 298 | * a gap of __SIGNAL_FRAMESIZE bytes | 288 | * a gap of __SIGNAL_FRAMESIZE bytes |
| 299 | * | 289 | * |
| 300 | * Each of these things must be a multiple of 16 bytes in size. | 290 | * Each of these things must be a multiple of 16 bytes in size. The following |
| 291 | * structure represent all of this except the __SIGNAL_FRAMESIZE gap | ||
| 301 | * | 292 | * |
| 302 | */ | 293 | */ |
| 303 | struct sigregs { | 294 | struct sigframe { |
| 295 | struct sigcontext sctx; /* the sigcontext */ | ||
| 304 | struct mcontext mctx; /* all the register values */ | 296 | struct mcontext mctx; /* all the register values */ |
| 305 | /* | 297 | /* |
| 306 | * Programs using the rs6000/xcoff abi can save up to 19 gp | 298 | * Programs using the rs6000/xcoff abi can save up to 19 gp |
| @@ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, | |||
| 703 | } | 695 | } |
| 704 | #endif /* CONFIG_PPC64 */ | 696 | #endif /* CONFIG_PPC64 */ |
| 705 | 697 | ||
| 706 | |||
| 707 | /* | ||
| 708 | * Restore the user process's signal mask | ||
| 709 | */ | ||
| 710 | #ifdef CONFIG_PPC64 | ||
| 711 | extern void restore_sigmask(sigset_t *set); | ||
| 712 | #else /* CONFIG_PPC64 */ | ||
| 713 | static void restore_sigmask(sigset_t *set) | ||
| 714 | { | ||
| 715 | sigdelsetmask(set, ~_BLOCKABLE); | ||
| 716 | spin_lock_irq(¤t->sighand->siglock); | ||
| 717 | current->blocked = *set; | ||
| 718 | recalc_sigpending(); | ||
| 719 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 720 | } | ||
| 721 | #endif | ||
| 722 | |||
| 723 | /* | 698 | /* |
| 724 | * Set up a signal frame for a "real-time" signal handler | 699 | * Set up a signal frame for a "real-time" signal handler |
| 725 | * (one which gets siginfo). | 700 | * (one which gets siginfo). |
| 726 | */ | 701 | */ |
| 727 | static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | 702 | int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, |
| 728 | siginfo_t *info, sigset_t *oldset, | 703 | siginfo_t *info, sigset_t *oldset, |
| 729 | struct pt_regs *regs, unsigned long newsp) | 704 | struct pt_regs *regs) |
| 730 | { | 705 | { |
| 731 | struct rt_sigframe __user *rt_sf; | 706 | struct rt_sigframe __user *rt_sf; |
| 732 | struct mcontext __user *frame; | 707 | struct mcontext __user *frame; |
| 733 | unsigned long origsp = newsp; | 708 | unsigned long newsp = 0; |
| 734 | 709 | ||
| 735 | /* Set up Signal Frame */ | 710 | /* Set up Signal Frame */ |
| 736 | /* Put a Real Time Context onto stack */ | 711 | /* Put a Real Time Context onto stack */ |
| 737 | newsp -= sizeof(*rt_sf); | 712 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); |
| 738 | rt_sf = (struct rt_sigframe __user *)newsp; | 713 | if (unlikely(rt_sf == NULL)) |
| 739 | |||
| 740 | /* create a stack frame for the caller of the handler */ | ||
| 741 | newsp -= __SIGNAL_FRAMESIZE + 16; | ||
| 742 | |||
| 743 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) | ||
| 744 | goto badframe; | 714 | goto badframe; |
| 745 | 715 | ||
| 746 | /* Put the siginfo & fill in most of the ucontext */ | 716 | /* Put the siginfo & fill in most of the ucontext */ |
| @@ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
| 770 | 740 | ||
| 771 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 741 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
| 772 | 742 | ||
| 743 | /* create a stack frame for the caller of the handler */ | ||
| 744 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | ||
| 773 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 745 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
| 774 | goto badframe; | 746 | goto badframe; |
| 747 | |||
| 748 | /* Fill registers for signal handler */ | ||
| 775 | regs->gpr[1] = newsp; | 749 | regs->gpr[1] = newsp; |
| 776 | regs->gpr[3] = sig; | 750 | regs->gpr[3] = sig; |
| 777 | regs->gpr[4] = (unsigned long) &rt_sf->info; | 751 | regs->gpr[4] = (unsigned long) &rt_sf->info; |
| @@ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1015 | /* | 989 | /* |
| 1016 | * OK, we're invoking a handler | 990 | * OK, we're invoking a handler |
| 1017 | */ | 991 | */ |
| 1018 | static int handle_signal(unsigned long sig, struct k_sigaction *ka, | 992 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, |
| 1019 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, | 993 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
| 1020 | unsigned long newsp) | ||
| 1021 | { | 994 | { |
| 1022 | struct sigcontext __user *sc; | 995 | struct sigcontext __user *sc; |
| 1023 | struct sigregs __user *frame; | 996 | struct sigframe __user *frame; |
| 1024 | unsigned long origsp = newsp; | 997 | unsigned long newsp = 0; |
| 1025 | 998 | ||
| 1026 | /* Set up Signal Frame */ | 999 | /* Set up Signal Frame */ |
| 1027 | newsp -= sizeof(struct sigregs); | 1000 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 1028 | frame = (struct sigregs __user *) newsp; | 1001 | if (unlikely(frame == NULL)) |
| 1029 | |||
| 1030 | /* Put a sigcontext on the stack */ | ||
| 1031 | newsp -= sizeof(*sc); | ||
| 1032 | sc = (struct sigcontext __user *) newsp; | ||
| 1033 | |||
| 1034 | /* create a stack frame for the caller of the handler */ | ||
| 1035 | newsp -= __SIGNAL_FRAMESIZE; | ||
| 1036 | |||
| 1037 | if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) | ||
| 1038 | goto badframe; | 1002 | goto badframe; |
| 1003 | sc = (struct sigcontext __user *) &frame->sctx; | ||
| 1039 | 1004 | ||
| 1040 | #if _NSIG != 64 | 1005 | #if _NSIG != 64 |
| 1041 | #error "Please adjust handle_signal()" | 1006 | #error "Please adjust handle_signal()" |
| @@ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
| 1047 | #else | 1012 | #else |
| 1048 | || __put_user(oldset->sig[1], &sc->_unused[3]) | 1013 | || __put_user(oldset->sig[1], &sc->_unused[3]) |
| 1049 | #endif | 1014 | #endif |
| 1050 | || __put_user(to_user_ptr(frame), &sc->regs) | 1015 | || __put_user(to_user_ptr(&frame->mctx), &sc->regs) |
| 1051 | || __put_user(sig, &sc->signal)) | 1016 | || __put_user(sig, &sc->signal)) |
| 1052 | goto badframe; | 1017 | goto badframe; |
| 1053 | 1018 | ||
| @@ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
| 1063 | 1028 | ||
| 1064 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1029 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
| 1065 | 1030 | ||
| 1031 | /* create a stack frame for the caller of the handler */ | ||
| 1032 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | ||
| 1066 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 1033 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
| 1067 | goto badframe; | 1034 | goto badframe; |
| 1035 | |||
| 1068 | regs->gpr[1] = newsp; | 1036 | regs->gpr[1] = newsp; |
| 1069 | regs->gpr[3] = sig; | 1037 | regs->gpr[3] = sig; |
| 1070 | regs->gpr[4] = (unsigned long) sc; | 1038 | regs->gpr[4] = (unsigned long) sc; |
| @@ -1126,106 +1094,3 @@ badframe: | |||
| 1126 | force_sig(SIGSEGV, current); | 1094 | force_sig(SIGSEGV, current); |
| 1127 | return 0; | 1095 | return 0; |
| 1128 | } | 1096 | } |
| 1129 | |||
| 1130 | /* | ||
| 1131 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
| 1132 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
| 1133 | * mistake. | ||
| 1134 | */ | ||
| 1135 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
| 1136 | { | ||
| 1137 | siginfo_t info; | ||
| 1138 | struct k_sigaction ka; | ||
| 1139 | unsigned int newsp; | ||
| 1140 | int signr, ret; | ||
| 1141 | |||
| 1142 | #ifdef CONFIG_PPC32 | ||
| 1143 | if (try_to_freeze()) { | ||
| 1144 | signr = 0; | ||
| 1145 | if (!signal_pending(current)) | ||
| 1146 | goto no_signal; | ||
| 1147 | } | ||
| 1148 | #endif | ||
| 1149 | |||
| 1150 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 1151 | oldset = ¤t->saved_sigmask; | ||
| 1152 | else if (!oldset) | ||
| 1153 | oldset = ¤t->blocked; | ||
| 1154 | |||
| 1155 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
| 1156 | #ifdef CONFIG_PPC32 | ||
| 1157 | no_signal: | ||
| 1158 | #endif | ||
| 1159 | if (TRAP(regs) == 0x0C00 /* System Call! */ | ||
| 1160 | && regs->ccr & 0x10000000 /* error signalled */ | ||
| 1161 | && ((ret = regs->gpr[3]) == ERESTARTSYS | ||
| 1162 | || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR | ||
| 1163 | || ret == ERESTART_RESTARTBLOCK)) { | ||
| 1164 | |||
| 1165 | if (signr > 0 | ||
| 1166 | && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK | ||
| 1167 | || (ret == ERESTARTSYS | ||
| 1168 | && !(ka.sa.sa_flags & SA_RESTART)))) { | ||
| 1169 | /* make the system call return an EINTR error */ | ||
| 1170 | regs->result = -EINTR; | ||
| 1171 | regs->gpr[3] = EINTR; | ||
| 1172 | /* note that the cr0.SO bit is already set */ | ||
| 1173 | } else { | ||
| 1174 | regs->nip -= 4; /* Back up & retry system call */ | ||
| 1175 | regs->result = 0; | ||
| 1176 | regs->trap = 0; | ||
| 1177 | if (ret == ERESTART_RESTARTBLOCK) | ||
| 1178 | regs->gpr[0] = __NR_restart_syscall; | ||
| 1179 | else | ||
| 1180 | regs->gpr[3] = regs->orig_gpr3; | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | if (signr == 0) { | ||
| 1185 | /* No signal to deliver -- put the saved sigmask back */ | ||
| 1186 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 1187 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 1188 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 1189 | } | ||
| 1190 | return 0; /* no signals delivered */ | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | ||
| 1194 | && !on_sig_stack(regs->gpr[1])) | ||
| 1195 | newsp = current->sas_ss_sp + current->sas_ss_size; | ||
| 1196 | else | ||
| 1197 | newsp = regs->gpr[1]; | ||
| 1198 | newsp &= ~0xfUL; | ||
| 1199 | |||
| 1200 | #ifdef CONFIG_PPC64 | ||
| 1201 | /* | ||
| 1202 | * Reenable the DABR before delivering the signal to | ||
| 1203 | * user space. The DABR will have been cleared if it | ||
| 1204 | * triggered inside the kernel. | ||
| 1205 | */ | ||
| 1206 | if (current->thread.dabr) | ||
| 1207 | set_dabr(current->thread.dabr); | ||
| 1208 | #endif | ||
| 1209 | |||
| 1210 | /* Whee! Actually deliver the signal. */ | ||
| 1211 | if (ka.sa.sa_flags & SA_SIGINFO) | ||
| 1212 | ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); | ||
| 1213 | else | ||
| 1214 | ret = handle_signal(signr, &ka, &info, oldset, regs, newsp); | ||
| 1215 | |||
| 1216 | if (ret) { | ||
| 1217 | spin_lock_irq(¤t->sighand->siglock); | ||
| 1218 | sigorsets(¤t->blocked, ¤t->blocked, | ||
| 1219 | &ka.sa.sa_mask); | ||
| 1220 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
| 1221 | sigaddset(¤t->blocked, signr); | ||
| 1222 | recalc_sigpending(); | ||
| 1223 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 1224 | /* A signal was successfully delivered; the saved sigmask is in | ||
| 1225 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
| 1226 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 1227 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | return ret; | ||
| 1231 | } | ||
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index b27e26852fdb..de895e6d8c62 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -34,9 +34,9 @@ | |||
| 34 | #include <asm/syscalls.h> | 34 | #include <asm/syscalls.h> |
| 35 | #include <asm/vdso.h> | 35 | #include <asm/vdso.h> |
| 36 | 36 | ||
| 37 | #define DEBUG_SIG 0 | 37 | #include "signal.h" |
| 38 | 38 | ||
| 39 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 39 | #define DEBUG_SIG 0 |
| 40 | 40 | ||
| 41 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) | 41 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) |
| 42 | #define FP_REGS_SIZE sizeof(elf_fpregset_t) | 42 | #define FP_REGS_SIZE sizeof(elf_fpregset_t) |
| @@ -64,14 +64,6 @@ struct rt_sigframe { | |||
| 64 | char abigap[288]; | 64 | char abigap[288]; |
| 65 | } __attribute__ ((aligned (16))); | 65 | } __attribute__ ((aligned (16))); |
| 66 | 66 | ||
| 67 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, | ||
| 68 | unsigned long r6, unsigned long r7, unsigned long r8, | ||
| 69 | struct pt_regs *regs) | ||
| 70 | { | ||
| 71 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
| 72 | } | ||
| 73 | |||
| 74 | |||
| 75 | /* | 67 | /* |
| 76 | * Set up the sigcontext for the signal frame. | 68 | * Set up the sigcontext for the signal frame. |
| 77 | */ | 69 | */ |
| @@ -208,25 +200,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
| 208 | } | 200 | } |
| 209 | 201 | ||
| 210 | /* | 202 | /* |
| 211 | * Allocate space for the signal frame | ||
| 212 | */ | ||
| 213 | static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
| 214 | size_t frame_size) | ||
| 215 | { | ||
| 216 | unsigned long newsp; | ||
| 217 | |||
| 218 | /* Default to using normal stack */ | ||
| 219 | newsp = regs->gpr[1]; | ||
| 220 | |||
| 221 | if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { | ||
| 222 | if (! on_sig_stack(regs->gpr[1])) | ||
| 223 | newsp = (current->sas_ss_sp + current->sas_ss_size); | ||
| 224 | } | ||
| 225 | |||
| 226 | return (void __user *)((newsp - frame_size) & -16ul); | ||
| 227 | } | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Setup the trampoline code on the stack | 203 | * Setup the trampoline code on the stack |
| 231 | */ | 204 | */ |
| 232 | static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | 205 | static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) |
| @@ -253,19 +226,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | |||
| 253 | } | 226 | } |
| 254 | 227 | ||
| 255 | /* | 228 | /* |
| 256 | * Restore the user process's signal mask (also used by signal32.c) | ||
| 257 | */ | ||
| 258 | void restore_sigmask(sigset_t *set) | ||
| 259 | { | ||
| 260 | sigdelsetmask(set, ~_BLOCKABLE); | ||
| 261 | spin_lock_irq(¤t->sighand->siglock); | ||
| 262 | current->blocked = *set; | ||
| 263 | recalc_sigpending(); | ||
| 264 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | /* | ||
| 269 | * Handle {get,set,swap}_context operations | 229 | * Handle {get,set,swap}_context operations |
| 270 | */ | 230 | */ |
| 271 | int sys_swapcontext(struct ucontext __user *old_ctx, | 231 | int sys_swapcontext(struct ucontext __user *old_ctx, |
| @@ -359,7 +319,7 @@ badframe: | |||
| 359 | return 0; | 319 | return 0; |
| 360 | } | 320 | } |
| 361 | 321 | ||
| 362 | static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | 322 | int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, |
| 363 | sigset_t *set, struct pt_regs *regs) | 323 | sigset_t *set, struct pt_regs *regs) |
| 364 | { | 324 | { |
| 365 | /* Handler is *really* a pointer to the function descriptor for | 325 | /* Handler is *really* a pointer to the function descriptor for |
| @@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
| 373 | long err = 0; | 333 | long err = 0; |
| 374 | 334 | ||
| 375 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 335 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 376 | 336 | if (unlikely(frame == NULL)) | |
| 377 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
| 378 | goto badframe; | 337 | goto badframe; |
| 379 | 338 | ||
| 380 | err |= __put_user(&frame->info, &frame->pinfo); | 339 | err |= __put_user(&frame->info, &frame->pinfo); |
| @@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
| 411 | funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; | 370 | funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; |
| 412 | 371 | ||
| 413 | /* Allocate a dummy caller frame for the signal handler. */ | 372 | /* Allocate a dummy caller frame for the signal handler. */ |
| 414 | newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; | 373 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; |
| 415 | err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); | 374 | err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); |
| 416 | 375 | ||
| 417 | /* Set up "regs" so we "return" to the signal handler. */ | 376 | /* Set up "regs" so we "return" to the signal handler. */ |
| @@ -442,134 +401,3 @@ badframe: | |||
| 442 | force_sigsegv(signr, current); | 401 | force_sigsegv(signr, current); |
| 443 | return 0; | 402 | return 0; |
| 444 | } | 403 | } |
| 445 | |||
| 446 | |||
| 447 | /* | ||
| 448 | * OK, we're invoking a handler | ||
| 449 | */ | ||
| 450 | static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||
| 451 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | ||
| 452 | { | ||
| 453 | int ret; | ||
| 454 | |||
| 455 | /* Set up Signal Frame */ | ||
| 456 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||
| 457 | |||
| 458 | if (ret) { | ||
| 459 | spin_lock_irq(¤t->sighand->siglock); | ||
| 460 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
| 461 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
| 462 | sigaddset(¤t->blocked,sig); | ||
| 463 | recalc_sigpending(); | ||
| 464 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 465 | } | ||
| 466 | |||
| 467 | return ret; | ||
| 468 | } | ||
| 469 | |||
| 470 | static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | ||
| 471 | { | ||
| 472 | switch ((int)regs->result) { | ||
| 473 | case -ERESTART_RESTARTBLOCK: | ||
| 474 | case -ERESTARTNOHAND: | ||
| 475 | /* ERESTARTNOHAND means that the syscall should only be | ||
| 476 | * restarted if there was no handler for the signal, and since | ||
| 477 | * we only get here if there is a handler, we dont restart. | ||
| 478 | */ | ||
| 479 | regs->result = -EINTR; | ||
| 480 | regs->gpr[3] = EINTR; | ||
| 481 | regs->ccr |= 0x10000000; | ||
| 482 | break; | ||
| 483 | case -ERESTARTSYS: | ||
| 484 | /* ERESTARTSYS means to restart the syscall if there is no | ||
| 485 | * handler or the handler was registered with SA_RESTART | ||
| 486 | */ | ||
| 487 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
| 488 | regs->result = -EINTR; | ||
| 489 | regs->gpr[3] = EINTR; | ||
| 490 | regs->ccr |= 0x10000000; | ||
| 491 | break; | ||
| 492 | } | ||
| 493 | /* fallthrough */ | ||
| 494 | case -ERESTARTNOINTR: | ||
| 495 | /* ERESTARTNOINTR means that the syscall should be | ||
| 496 | * called again after the signal handler returns. | ||
| 497 | */ | ||
| 498 | regs->gpr[3] = regs->orig_gpr3; | ||
| 499 | regs->nip -= 4; | ||
| 500 | regs->result = 0; | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | } | ||
| 504 | |||
| 505 | /* | ||
| 506 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
| 507 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
| 508 | * mistake. | ||
| 509 | */ | ||
| 510 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
| 511 | { | ||
| 512 | siginfo_t info; | ||
| 513 | int signr; | ||
| 514 | struct k_sigaction ka; | ||
| 515 | |||
| 516 | /* | ||
| 517 | * If the current thread is 32 bit - invoke the | ||
| 518 | * 32 bit signal handling code | ||
| 519 | */ | ||
| 520 | if (test_thread_flag(TIF_32BIT)) | ||
| 521 | return do_signal32(oldset, regs); | ||
| 522 | |||
| 523 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 524 | oldset = ¤t->saved_sigmask; | ||
| 525 | else if (!oldset) | ||
| 526 | oldset = ¤t->blocked; | ||
| 527 | |||
| 528 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
| 529 | if (signr > 0) { | ||
| 530 | int ret; | ||
| 531 | |||
| 532 | /* Whee! Actually deliver the signal. */ | ||
| 533 | if (TRAP(regs) == 0x0C00) | ||
| 534 | syscall_restart(regs, &ka); | ||
| 535 | |||
| 536 | /* | ||
| 537 | * Reenable the DABR before delivering the signal to | ||
| 538 | * user space. The DABR will have been cleared if it | ||
| 539 | * triggered inside the kernel. | ||
| 540 | */ | ||
| 541 | if (current->thread.dabr) | ||
| 542 | set_dabr(current->thread.dabr); | ||
| 543 | |||
| 544 | ret = handle_signal(signr, &ka, &info, oldset, regs); | ||
| 545 | |||
| 546 | /* If a signal was successfully delivered, the saved sigmask is in | ||
| 547 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
| 548 | if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 549 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 550 | |||
| 551 | return ret; | ||
| 552 | } | ||
| 553 | |||
| 554 | if (TRAP(regs) == 0x0C00) { /* System Call! */ | ||
| 555 | if ((int)regs->result == -ERESTARTNOHAND || | ||
| 556 | (int)regs->result == -ERESTARTSYS || | ||
| 557 | (int)regs->result == -ERESTARTNOINTR) { | ||
| 558 | regs->gpr[3] = regs->orig_gpr3; | ||
| 559 | regs->nip -= 4; /* Back up & retry system call */ | ||
| 560 | regs->result = 0; | ||
| 561 | } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { | ||
| 562 | regs->gpr[0] = __NR_restart_syscall; | ||
| 563 | regs->nip -= 4; | ||
| 564 | regs->result = 0; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | /* No signal to deliver -- put the saved sigmask back */ | ||
| 568 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 569 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 570 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 571 | } | ||
| 572 | |||
| 573 | return 0; | ||
| 574 | } | ||
| 575 | EXPORT_SYMBOL(do_signal); | ||
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 68991c2d4a1b..55d29ed4b7a0 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid) | |||
| 442 | return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, | 442 | return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, |
| 443 | kobject_name(&dev->kobj)); | 443 | kobject_name(&dev->kobj)); |
| 444 | } | 444 | } |
| 445 | EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||
| 445 | 446 | ||
| 446 | void sysfs_remove_device_from_node(struct sys_device *dev, int nid) | 447 | void sysfs_remove_device_from_node(struct sys_device *dev, int nid) |
| 447 | { | 448 | { |
| 448 | struct node *node = &node_devices[nid]; | 449 | struct node *node = &node_devices[nid]; |
| 449 | sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); | 450 | sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); |
| 450 | } | 451 | } |
| 452 | EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||
| 451 | 453 | ||
| 452 | #else | 454 | #else |
| 453 | static void register_nodes(void) | 455 | static void register_nodes(void) |
| @@ -457,9 +459,6 @@ static void register_nodes(void) | |||
| 457 | 459 | ||
| 458 | #endif | 460 | #endif |
| 459 | 461 | ||
| 460 | EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||
| 461 | EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||
| 462 | |||
| 463 | /* Only valid if CPU is present. */ | 462 | /* Only valid if CPU is present. */ |
| 464 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) | 463 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) |
| 465 | { | 464 | { |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2c8564d54e4d..e5df167f7824 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -77,9 +77,8 @@ | |||
| 77 | /* keep track of when we need to update the rtc */ | 77 | /* keep track of when we need to update the rtc */ |
| 78 | time_t last_rtc_update; | 78 | time_t last_rtc_update; |
| 79 | #ifdef CONFIG_PPC_ISERIES | 79 | #ifdef CONFIG_PPC_ISERIES |
| 80 | unsigned long iSeries_recal_titan = 0; | 80 | static unsigned long __initdata iSeries_recal_titan; |
| 81 | unsigned long iSeries_recal_tb = 0; | 81 | static signed long __initdata iSeries_recal_tb; |
| 82 | static unsigned long first_settimeofday = 1; | ||
| 83 | #endif | 82 | #endif |
| 84 | 83 | ||
| 85 | /* The decrementer counts down by 128 every 128ns on a 601. */ | 84 | /* The decrementer counts down by 128 every 128ns on a 601. */ |
| @@ -113,8 +112,9 @@ u64 ticklen_to_xs; /* 0.64 fraction */ | |||
| 113 | DEFINE_SPINLOCK(rtc_lock); | 112 | DEFINE_SPINLOCK(rtc_lock); |
| 114 | EXPORT_SYMBOL_GPL(rtc_lock); | 113 | EXPORT_SYMBOL_GPL(rtc_lock); |
| 115 | 114 | ||
| 116 | u64 tb_to_ns_scale; | 115 | static u64 tb_to_ns_scale __read_mostly; |
| 117 | unsigned tb_to_ns_shift; | 116 | static unsigned tb_to_ns_shift __read_mostly; |
| 117 | static unsigned long boot_tb __read_mostly; | ||
| 118 | 118 | ||
| 119 | struct gettimeofday_struct do_gtod; | 119 | struct gettimeofday_struct do_gtod; |
| 120 | 120 | ||
| @@ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs) | |||
| 214 | run_posix_cpu_timers(current); | 214 | run_posix_cpu_timers(current); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | #ifdef CONFIG_PPC_SPLPAR | ||
| 218 | /* | 217 | /* |
| 219 | * Stuff for accounting stolen time. | 218 | * Stuff for accounting stolen time. |
| 220 | */ | 219 | */ |
| @@ -222,19 +221,28 @@ struct cpu_purr_data { | |||
| 222 | int initialized; /* thread is running */ | 221 | int initialized; /* thread is running */ |
| 223 | u64 tb; /* last TB value read */ | 222 | u64 tb; /* last TB value read */ |
| 224 | u64 purr; /* last PURR value read */ | 223 | u64 purr; /* last PURR value read */ |
| 225 | spinlock_t lock; | ||
| 226 | }; | 224 | }; |
| 227 | 225 | ||
| 226 | /* | ||
| 227 | * Each entry in the cpu_purr_data array is manipulated only by its | ||
| 228 | * "owner" cpu -- usually in the timer interrupt but also occasionally | ||
| 229 | * in process context for cpu online. As long as cpus do not touch | ||
| 230 | * each others' cpu_purr_data, disabling local interrupts is | ||
| 231 | * sufficient to serialize accesses. | ||
| 232 | */ | ||
| 228 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | 233 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); |
| 229 | 234 | ||
| 230 | static void snapshot_tb_and_purr(void *data) | 235 | static void snapshot_tb_and_purr(void *data) |
| 231 | { | 236 | { |
| 237 | unsigned long flags; | ||
| 232 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | 238 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); |
| 233 | 239 | ||
| 240 | local_irq_save(flags); | ||
| 234 | p->tb = mftb(); | 241 | p->tb = mftb(); |
| 235 | p->purr = mfspr(SPRN_PURR); | 242 | p->purr = mfspr(SPRN_PURR); |
| 236 | wmb(); | 243 | wmb(); |
| 237 | p->initialized = 1; | 244 | p->initialized = 1; |
| 245 | local_irq_restore(flags); | ||
| 238 | } | 246 | } |
| 239 | 247 | ||
| 240 | /* | 248 | /* |
| @@ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data) | |||
| 242 | */ | 250 | */ |
| 243 | void snapshot_timebases(void) | 251 | void snapshot_timebases(void) |
| 244 | { | 252 | { |
| 245 | int cpu; | ||
| 246 | |||
| 247 | if (!cpu_has_feature(CPU_FTR_PURR)) | 253 | if (!cpu_has_feature(CPU_FTR_PURR)) |
| 248 | return; | 254 | return; |
| 249 | for_each_possible_cpu(cpu) | ||
| 250 | spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); | ||
| 251 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); | 255 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); |
| 252 | } | 256 | } |
| 253 | 257 | ||
| 258 | /* | ||
| 259 | * Must be called with interrupts disabled. | ||
| 260 | */ | ||
| 254 | void calculate_steal_time(void) | 261 | void calculate_steal_time(void) |
| 255 | { | 262 | { |
| 256 | u64 tb, purr; | 263 | u64 tb, purr; |
| @@ -262,7 +269,6 @@ void calculate_steal_time(void) | |||
| 262 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); | 269 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
| 263 | if (!pme->initialized) | 270 | if (!pme->initialized) |
| 264 | return; /* this can happen in early boot */ | 271 | return; /* this can happen in early boot */ |
| 265 | spin_lock(&pme->lock); | ||
| 266 | tb = mftb(); | 272 | tb = mftb(); |
| 267 | purr = mfspr(SPRN_PURR); | 273 | purr = mfspr(SPRN_PURR); |
| 268 | stolen = (tb - pme->tb) - (purr - pme->purr); | 274 | stolen = (tb - pme->tb) - (purr - pme->purr); |
| @@ -270,9 +276,9 @@ void calculate_steal_time(void) | |||
| 270 | account_steal_time(current, stolen); | 276 | account_steal_time(current, stolen); |
| 271 | pme->tb = tb; | 277 | pme->tb = tb; |
| 272 | pme->purr = purr; | 278 | pme->purr = purr; |
| 273 | spin_unlock(&pme->lock); | ||
| 274 | } | 279 | } |
| 275 | 280 | ||
| 281 | #ifdef CONFIG_PPC_SPLPAR | ||
| 276 | /* | 282 | /* |
| 277 | * Must be called before the cpu is added to the online map when | 283 | * Must be called before the cpu is added to the online map when |
| 278 | * a cpu is being brought up at runtime. | 284 | * a cpu is being brought up at runtime. |
| @@ -284,12 +290,12 @@ static void snapshot_purr(void) | |||
| 284 | 290 | ||
| 285 | if (!cpu_has_feature(CPU_FTR_PURR)) | 291 | if (!cpu_has_feature(CPU_FTR_PURR)) |
| 286 | return; | 292 | return; |
| 293 | local_irq_save(flags); | ||
| 287 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); | 294 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
| 288 | spin_lock_irqsave(&pme->lock, flags); | ||
| 289 | pme->tb = mftb(); | 295 | pme->tb = mftb(); |
| 290 | pme->purr = mfspr(SPRN_PURR); | 296 | pme->purr = mfspr(SPRN_PURR); |
| 291 | pme->initialized = 1; | 297 | pme->initialized = 1; |
| 292 | spin_unlock_irqrestore(&pme->lock, flags); | 298 | local_irq_restore(flags); |
| 293 | } | 299 | } |
| 294 | 300 | ||
| 295 | #endif /* CONFIG_PPC_SPLPAR */ | 301 | #endif /* CONFIG_PPC_SPLPAR */ |
| @@ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc); | |||
| 550 | * returned by the service processor for the timebase frequency. | 556 | * returned by the service processor for the timebase frequency. |
| 551 | */ | 557 | */ |
| 552 | 558 | ||
| 553 | static void iSeries_tb_recal(void) | 559 | static int __init iSeries_tb_recal(void) |
| 554 | { | 560 | { |
| 555 | struct div_result divres; | 561 | struct div_result divres; |
| 556 | unsigned long titan, tb; | 562 | unsigned long titan, tb; |
| 563 | |||
| 564 | /* Make sure we only run on iSeries */ | ||
| 565 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 566 | return -ENODEV; | ||
| 567 | |||
| 557 | tb = get_tb(); | 568 | tb = get_tb(); |
| 558 | titan = HvCallXm_loadTod(); | 569 | titan = HvCallXm_loadTod(); |
| 559 | if ( iSeries_recal_titan ) { | 570 | if ( iSeries_recal_titan ) { |
| @@ -594,8 +605,18 @@ static void iSeries_tb_recal(void) | |||
| 594 | } | 605 | } |
| 595 | iSeries_recal_titan = titan; | 606 | iSeries_recal_titan = titan; |
| 596 | iSeries_recal_tb = tb; | 607 | iSeries_recal_tb = tb; |
| 608 | |||
| 609 | return 0; | ||
| 597 | } | 610 | } |
| 598 | #endif | 611 | late_initcall(iSeries_tb_recal); |
| 612 | |||
| 613 | /* Called from platform early init */ | ||
| 614 | void __init iSeries_time_init_early(void) | ||
| 615 | { | ||
| 616 | iSeries_recal_tb = get_tb(); | ||
| 617 | iSeries_recal_titan = HvCallXm_loadTod(); | ||
| 618 | } | ||
| 619 | #endif /* CONFIG_PPC_ISERIES */ | ||
| 599 | 620 | ||
| 600 | /* | 621 | /* |
| 601 | * For iSeries shared processors, we have to let the hypervisor | 622 | * For iSeries shared processors, we have to let the hypervisor |
| @@ -735,7 +756,7 @@ unsigned long long sched_clock(void) | |||
| 735 | { | 756 | { |
| 736 | if (__USE_RTC()) | 757 | if (__USE_RTC()) |
| 737 | return get_rtc(); | 758 | return get_rtc(); |
| 738 | return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; | 759 | return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; |
| 739 | } | 760 | } |
| 740 | 761 | ||
| 741 | int do_settimeofday(struct timespec *tv) | 762 | int do_settimeofday(struct timespec *tv) |
| @@ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv) | |||
| 759 | * to the RTC again, or write to the RTC but then they don't call | 780 | * to the RTC again, or write to the RTC but then they don't call |
| 760 | * settimeofday to perform this operation. | 781 | * settimeofday to perform this operation. |
| 761 | */ | 782 | */ |
| 762 | #ifdef CONFIG_PPC_ISERIES | ||
| 763 | if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { | ||
| 764 | iSeries_tb_recal(); | ||
| 765 | first_settimeofday = 0; | ||
| 766 | } | ||
| 767 | #endif | ||
| 768 | 783 | ||
| 769 | /* Make userspace gettimeofday spin until we're done. */ | 784 | /* Make userspace gettimeofday spin until we're done. */ |
| 770 | ++vdso_data->tb_update_count; | 785 | ++vdso_data->tb_update_count; |
| @@ -960,6 +975,8 @@ void __init time_init(void) | |||
| 960 | } | 975 | } |
| 961 | tb_to_ns_scale = scale; | 976 | tb_to_ns_scale = scale; |
| 962 | tb_to_ns_shift = shift; | 977 | tb_to_ns_shift = shift; |
| 978 | /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ | ||
| 979 | boot_tb = get_tb(); | ||
| 963 | 980 | ||
| 964 | tm = get_boot_time(); | 981 | tm = get_boot_time(); |
| 965 | 982 | ||
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 4245579edb4e..cef01e4e8989 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -670,7 +670,7 @@ static int __init vdso_init(void) | |||
| 670 | /* | 670 | /* |
| 671 | * Fill up the "systemcfg" stuff for backward compatiblity | 671 | * Fill up the "systemcfg" stuff for backward compatiblity |
| 672 | */ | 672 | */ |
| 673 | strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); | 673 | strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); |
| 674 | vdso_data->version.major = SYSTEMCFG_MAJOR; | 674 | vdso_data->version.major = SYSTEMCFG_MAJOR; |
| 675 | vdso_data->version.minor = SYSTEMCFG_MINOR; | 675 | vdso_data->version.minor = SYSTEMCFG_MINOR; |
| 676 | vdso_data->processor = mfspr(SPRN_PVR); | 676 | vdso_data->processor = mfspr(SPRN_PVR); |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 21c39ff2dc39..ae4acd84143d 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #define PROVIDE32(x) PROVIDE(x) | 7 | #define PROVIDE32(x) PROVIDE(x) |
| 8 | #endif | 8 | #endif |
| 9 | #include <asm-generic/vmlinux.lds.h> | 9 | #include <asm-generic/vmlinux.lds.h> |
| 10 | #include <asm/cache.h> | ||
| 10 | 11 | ||
| 11 | ENTRY(_stext) | 12 | ENTRY(_stext) |
| 12 | 13 | ||
| @@ -211,6 +212,11 @@ SECTIONS | |||
| 211 | *(.data.cacheline_aligned) | 212 | *(.data.cacheline_aligned) |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 215 | . = ALIGN(L1_CACHE_BYTES); | ||
| 216 | .data.read_mostly : { | ||
| 217 | *(.data.read_mostly) | ||
| 218 | } | ||
| 219 | |||
| 214 | . = ALIGN(PAGE_SIZE); | 220 | . = ALIGN(PAGE_SIZE); |
| 215 | __data_nosave : { | 221 | __data_nosave : { |
| 216 | __nosave_begin = .; | 222 | __nosave_begin = .; |
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index ca4dcb07a939..c3df50476539 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 14 | * Copyright (C) 1996 Paul Mackerras | 14 | * Copyright (C) 1996 Paul Mackerras |
| 15 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 16 | * | 15 | * |
| 17 | * Derived from "arch/i386/mm/init.c" | 16 | * Derived from "arch/i386/mm/init.c" |
| 18 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c index 838e09db71d9..7ff2609b64d1 100644 --- a/arch/powerpc/mm/4xx_mmu.c +++ b/arch/powerpc/mm/4xx_mmu.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 11 | * Copyright (C) 1996 Paul Mackerras | 11 | * Copyright (C) 1996 Paul Mackerras |
| 12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 13 | * | 12 | * |
| 14 | * Derived from "arch/i386/mm/init.c" | 13 | * Derived from "arch/i386/mm/init.c" |
| 15 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 4f839c6a9768..7e4d27ad3dee 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o | |||
| 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
| 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ | 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ |
| 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ | 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ |
| 14 | slb_low.o slb.o stab.o mmap.o imalloc.o \ | 14 | slb_low.o slb.o stab.o mmap.o $(hash-y) |
| 15 | $(hash-y) | ||
| 16 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o | 15 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o |
| 17 | obj-$(CONFIG_40x) += 4xx_mmu.o | 16 | obj-$(CONFIG_40x) += 4xx_mmu.o |
| 18 | obj-$(CONFIG_44x) += 44x_mmu.o | 17 | obj-$(CONFIG_44x) += 44x_mmu.o |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 115b25f50bf8..0ece51310bfe 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -380,7 +380,7 @@ out_of_memory: | |||
| 380 | } | 380 | } |
| 381 | printk("VM: killing process %s\n", current->comm); | 381 | printk("VM: killing process %s\n", current->comm); |
| 382 | if (user_mode(regs)) | 382 | if (user_mode(regs)) |
| 383 | do_exit(SIGKILL); | 383 | do_group_exit(SIGKILL); |
| 384 | return SIGKILL; | 384 | return SIGKILL; |
| 385 | 385 | ||
| 386 | do_sigbus: | 386 | do_sigbus: |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index 123da03ab118..afab247d472f 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 16 | * Copyright (C) 1996 Paul Mackerras | 16 | * Copyright (C) 1996 Paul Mackerras |
| 17 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 18 | * | 17 | * |
| 19 | * Derived from "arch/i386/mm/init.c" | 18 | * Derived from "arch/i386/mm/init.c" |
| 20 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 19 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 4a20d890e2f4..6ba9b47e55af 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
| @@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local) | |||
| 104 | spin_unlock(&native_tlbie_lock); | 104 | spin_unlock(&native_tlbie_lock); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | static inline void native_lock_hpte(hpte_t *hptep) | 107 | static inline void native_lock_hpte(struct hash_pte *hptep) |
| 108 | { | 108 | { |
| 109 | unsigned long *word = &hptep->v; | 109 | unsigned long *word = &hptep->v; |
| 110 | 110 | ||
| @@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep) | |||
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static inline void native_unlock_hpte(hpte_t *hptep) | 119 | static inline void native_unlock_hpte(struct hash_pte *hptep) |
| 120 | { | 120 | { |
| 121 | unsigned long *word = &hptep->v; | 121 | unsigned long *word = &hptep->v; |
| 122 | 122 | ||
| @@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 128 | unsigned long pa, unsigned long rflags, | 128 | unsigned long pa, unsigned long rflags, |
| 129 | unsigned long vflags, int psize) | 129 | unsigned long vflags, int psize) |
| 130 | { | 130 | { |
| 131 | hpte_t *hptep = htab_address + hpte_group; | 131 | struct hash_pte *hptep = htab_address + hpte_group; |
| 132 | unsigned long hpte_v, hpte_r; | 132 | unsigned long hpte_v, hpte_r; |
| 133 | int i; | 133 | int i; |
| 134 | 134 | ||
| @@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 163 | 163 | ||
| 164 | hptep->r = hpte_r; | 164 | hptep->r = hpte_r; |
| 165 | /* Guarantee the second dword is visible before the valid bit */ | 165 | /* Guarantee the second dword is visible before the valid bit */ |
| 166 | __asm__ __volatile__ ("eieio" : : : "memory"); | 166 | eieio(); |
| 167 | /* | 167 | /* |
| 168 | * Now set the first dword including the valid bit | 168 | * Now set the first dword including the valid bit |
| 169 | * NOTE: this also unlocks the hpte | 169 | * NOTE: this also unlocks the hpte |
| @@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 177 | 177 | ||
| 178 | static long native_hpte_remove(unsigned long hpte_group) | 178 | static long native_hpte_remove(unsigned long hpte_group) |
| 179 | { | 179 | { |
| 180 | hpte_t *hptep; | 180 | struct hash_pte *hptep; |
| 181 | int i; | 181 | int i; |
| 182 | int slot_offset; | 182 | int slot_offset; |
| 183 | unsigned long hpte_v; | 183 | unsigned long hpte_v; |
| @@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group) | |||
| 217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | 217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, |
| 218 | unsigned long va, int psize, int local) | 218 | unsigned long va, int psize, int local) |
| 219 | { | 219 | { |
| 220 | hpte_t *hptep = htab_address + slot; | 220 | struct hash_pte *hptep = htab_address + slot; |
| 221 | unsigned long hpte_v, want_v; | 221 | unsigned long hpte_v, want_v; |
| 222 | int ret = 0; | 222 | int ret = 0; |
| 223 | 223 | ||
| @@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 233 | /* Even if we miss, we need to invalidate the TLB */ | 233 | /* Even if we miss, we need to invalidate the TLB */ |
| 234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | 234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { |
| 235 | DBG_LOW(" -> miss\n"); | 235 | DBG_LOW(" -> miss\n"); |
| 236 | native_unlock_hpte(hptep); | ||
| 237 | ret = -1; | 236 | ret = -1; |
| 238 | } else { | 237 | } else { |
| 239 | DBG_LOW(" -> hit\n"); | 238 | DBG_LOW(" -> hit\n"); |
| 240 | /* Update the HPTE */ | 239 | /* Update the HPTE */ |
| 241 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | 240 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | |
| 242 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); | 241 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); |
| 243 | native_unlock_hpte(hptep); | ||
| 244 | } | 242 | } |
| 243 | native_unlock_hpte(hptep); | ||
| 245 | 244 | ||
| 246 | /* Ensure it is out of the tlb too. */ | 245 | /* Ensure it is out of the tlb too. */ |
| 247 | tlbie(va, psize, local); | 246 | tlbie(va, psize, local); |
| @@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 251 | 250 | ||
| 252 | static long native_hpte_find(unsigned long va, int psize) | 251 | static long native_hpte_find(unsigned long va, int psize) |
| 253 | { | 252 | { |
| 254 | hpte_t *hptep; | 253 | struct hash_pte *hptep; |
| 255 | unsigned long hash; | 254 | unsigned long hash; |
| 256 | unsigned long i, j; | 255 | unsigned long i, j; |
| 257 | long slot; | 256 | long slot; |
| @@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
| 294 | { | 293 | { |
| 295 | unsigned long vsid, va; | 294 | unsigned long vsid, va; |
| 296 | long slot; | 295 | long slot; |
| 297 | hpte_t *hptep; | 296 | struct hash_pte *hptep; |
| 298 | 297 | ||
| 299 | vsid = get_kernel_vsid(ea); | 298 | vsid = get_kernel_vsid(ea); |
| 300 | va = (vsid << 28) | (ea & 0x0fffffff); | 299 | va = (vsid << 28) | (ea & 0x0fffffff); |
| @@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
| 315 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, | 314 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, |
| 316 | int psize, int local) | 315 | int psize, int local) |
| 317 | { | 316 | { |
| 318 | hpte_t *hptep = htab_address + slot; | 317 | struct hash_pte *hptep = htab_address + slot; |
| 319 | unsigned long hpte_v; | 318 | unsigned long hpte_v; |
| 320 | unsigned long want_v; | 319 | unsigned long want_v; |
| 321 | unsigned long flags; | 320 | unsigned long flags; |
| @@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 345 | #define LP_BITS 8 | 344 | #define LP_BITS 8 |
| 346 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) | 345 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) |
| 347 | 346 | ||
| 348 | static void hpte_decode(hpte_t *hpte, unsigned long slot, | 347 | static void hpte_decode(struct hash_pte *hpte, unsigned long slot, |
| 349 | int *psize, unsigned long *va) | 348 | int *psize, unsigned long *va) |
| 350 | { | 349 | { |
| 351 | unsigned long hpte_r = hpte->r; | 350 | unsigned long hpte_r = hpte->r; |
| @@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, | |||
| 415 | static void native_hpte_clear(void) | 414 | static void native_hpte_clear(void) |
| 416 | { | 415 | { |
| 417 | unsigned long slot, slots, flags; | 416 | unsigned long slot, slots, flags; |
| 418 | hpte_t *hptep = htab_address; | 417 | struct hash_pte *hptep = htab_address; |
| 419 | unsigned long hpte_v, va; | 418 | unsigned long hpte_v, va; |
| 420 | unsigned long pteg_count; | 419 | unsigned long pteg_count; |
| 421 | int psize; | 420 | int psize; |
| @@ -462,7 +461,7 @@ static void native_hpte_clear(void) | |||
| 462 | static void native_flush_hash_range(unsigned long number, int local) | 461 | static void native_flush_hash_range(unsigned long number, int local) |
| 463 | { | 462 | { |
| 464 | unsigned long va, hash, index, hidx, shift, slot; | 463 | unsigned long va, hash, index, hidx, shift, slot; |
| 465 | hpte_t *hptep; | 464 | struct hash_pte *hptep; |
| 466 | unsigned long hpte_v; | 465 | unsigned long hpte_v; |
| 467 | unsigned long want_v; | 466 | unsigned long want_v; |
| 468 | unsigned long flags; | 467 | unsigned long flags; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 4f2f4534a9d8..2ce9491b48d4 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -87,7 +87,7 @@ extern unsigned long dart_tablebase; | |||
| 87 | static unsigned long _SDR1; | 87 | static unsigned long _SDR1; |
| 88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | 88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
| 89 | 89 | ||
| 90 | hpte_t *htab_address; | 90 | struct hash_pte *htab_address; |
| 91 | unsigned long htab_size_bytes; | 91 | unsigned long htab_size_bytes; |
| 92 | unsigned long htab_hash_mask; | 92 | unsigned long htab_hash_mask; |
| 93 | int mmu_linear_psize = MMU_PAGE_4K; | 93 | int mmu_linear_psize = MMU_PAGE_4K; |
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c deleted file mode 100644 index c831815c31f0..000000000000 --- a/arch/powerpc/mm/imalloc.c +++ /dev/null | |||
| @@ -1,313 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * c 2001 PPC 64 Team, IBM Corp | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/slab.h> | ||
| 11 | #include <linux/vmalloc.h> | ||
| 12 | |||
| 13 | #include <asm/uaccess.h> | ||
| 14 | #include <asm/pgalloc.h> | ||
| 15 | #include <asm/pgtable.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <asm/cacheflush.h> | ||
| 18 | |||
| 19 | #include "mmu_decl.h" | ||
| 20 | |||
| 21 | static DEFINE_MUTEX(imlist_mutex); | ||
| 22 | struct vm_struct * imlist = NULL; | ||
| 23 | |||
| 24 | static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | ||
| 25 | { | ||
| 26 | unsigned long addr; | ||
| 27 | struct vm_struct **p, *tmp; | ||
| 28 | |||
| 29 | addr = ioremap_bot; | ||
| 30 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
| 31 | if (size + addr < (unsigned long) tmp->addr) | ||
| 32 | break; | ||
| 33 | if ((unsigned long)tmp->addr >= ioremap_bot) | ||
| 34 | addr = tmp->size + (unsigned long) tmp->addr; | ||
| 35 | if (addr >= IMALLOC_END-size) | ||
| 36 | return 1; | ||
| 37 | } | ||
| 38 | *im_addr = addr; | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | /* Return whether the region described by v_addr and size is a subset | ||
| 44 | * of the region described by parent | ||
| 45 | */ | ||
| 46 | static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, | ||
| 47 | struct vm_struct *parent) | ||
| 48 | { | ||
| 49 | return (int) (v_addr >= (unsigned long) parent->addr && | ||
| 50 | v_addr < (unsigned long) parent->addr + parent->size && | ||
| 51 | size < parent->size); | ||
| 52 | } | ||
| 53 | |||
| 54 | /* Return whether the region described by v_addr and size is a superset | ||
| 55 | * of the region described by child | ||
| 56 | */ | ||
| 57 | static int im_region_is_superset(unsigned long v_addr, unsigned long size, | ||
| 58 | struct vm_struct *child) | ||
| 59 | { | ||
| 60 | struct vm_struct parent; | ||
| 61 | |||
| 62 | parent.addr = (void *) v_addr; | ||
| 63 | parent.size = size; | ||
| 64 | |||
| 65 | return im_region_is_subset((unsigned long) child->addr, child->size, | ||
| 66 | &parent); | ||
| 67 | } | ||
| 68 | |||
| 69 | /* Return whether the region described by v_addr and size overlaps | ||
| 70 | * the region described by vm. Overlapping regions meet the | ||
| 71 | * following conditions: | ||
| 72 | * 1) The regions share some part of the address space | ||
| 73 | * 2) The regions aren't identical | ||
| 74 | * 3) Neither region is a subset of the other | ||
| 75 | */ | ||
| 76 | static int im_region_overlaps(unsigned long v_addr, unsigned long size, | ||
| 77 | struct vm_struct *vm) | ||
| 78 | { | ||
| 79 | if (im_region_is_superset(v_addr, size, vm)) | ||
| 80 | return 0; | ||
| 81 | |||
| 82 | return (v_addr + size > (unsigned long) vm->addr + vm->size && | ||
| 83 | v_addr < (unsigned long) vm->addr + vm->size) || | ||
| 84 | (v_addr < (unsigned long) vm->addr && | ||
| 85 | v_addr + size > (unsigned long) vm->addr); | ||
| 86 | } | ||
| 87 | |||
| 88 | /* Determine imalloc status of region described by v_addr and size. | ||
| 89 | * Can return one of the following: | ||
| 90 | * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. | ||
| 91 | * IM_REGION_SUBSET - Region is a subset of a region that is already | ||
| 92 | * allocated in imalloc space. | ||
| 93 | * vm will be assigned to a ptr to the parent region. | ||
| 94 | * IM_REGION_EXISTS - Exact region already allocated in imalloc space. | ||
| 95 | * vm will be assigned to a ptr to the existing imlist | ||
| 96 | * member. | ||
| 97 | * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space. | ||
| 98 | * IM_REGION_SUPERSET - Region is a superset of a region that is already | ||
| 99 | * allocated in imalloc space. | ||
| 100 | */ | ||
| 101 | static int im_region_status(unsigned long v_addr, unsigned long size, | ||
| 102 | struct vm_struct **vm) | ||
| 103 | { | ||
| 104 | struct vm_struct *tmp; | ||
| 105 | |||
| 106 | for (tmp = imlist; tmp; tmp = tmp->next) | ||
| 107 | if (v_addr < (unsigned long) tmp->addr + tmp->size) | ||
| 108 | break; | ||
| 109 | |||
| 110 | *vm = NULL; | ||
| 111 | if (tmp) { | ||
| 112 | if (im_region_overlaps(v_addr, size, tmp)) | ||
| 113 | return IM_REGION_OVERLAP; | ||
| 114 | |||
| 115 | *vm = tmp; | ||
| 116 | if (im_region_is_subset(v_addr, size, tmp)) { | ||
| 117 | /* Return with tmp pointing to superset */ | ||
| 118 | return IM_REGION_SUBSET; | ||
| 119 | } | ||
| 120 | if (im_region_is_superset(v_addr, size, tmp)) { | ||
| 121 | /* Return with tmp pointing to first subset */ | ||
| 122 | return IM_REGION_SUPERSET; | ||
| 123 | } | ||
| 124 | else if (v_addr == (unsigned long) tmp->addr && | ||
| 125 | size == tmp->size) { | ||
| 126 | /* Return with tmp pointing to exact region */ | ||
| 127 | return IM_REGION_EXISTS; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return IM_REGION_UNUSED; | ||
| 132 | } | ||
| 133 | |||
| 134 | static struct vm_struct * split_im_region(unsigned long v_addr, | ||
| 135 | unsigned long size, struct vm_struct *parent) | ||
| 136 | { | ||
| 137 | struct vm_struct *vm1 = NULL; | ||
| 138 | struct vm_struct *vm2 = NULL; | ||
| 139 | struct vm_struct *new_vm = NULL; | ||
| 140 | |||
| 141 | vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); | ||
| 142 | if (vm1 == NULL) { | ||
| 143 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
| 144 | return NULL; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (v_addr == (unsigned long) parent->addr) { | ||
| 148 | /* Use existing parent vm_struct to represent child, allocate | ||
| 149 | * new one for the remainder of parent range | ||
| 150 | */ | ||
| 151 | vm1->size = parent->size - size; | ||
| 152 | vm1->addr = (void *) (v_addr + size); | ||
| 153 | vm1->next = parent->next; | ||
| 154 | |||
| 155 | parent->size = size; | ||
| 156 | parent->next = vm1; | ||
| 157 | new_vm = parent; | ||
| 158 | } else if (v_addr + size == (unsigned long) parent->addr + | ||
| 159 | parent->size) { | ||
| 160 | /* Allocate new vm_struct to represent child, use existing | ||
| 161 | * parent one for remainder of parent range | ||
| 162 | */ | ||
| 163 | vm1->size = size; | ||
| 164 | vm1->addr = (void *) v_addr; | ||
| 165 | vm1->next = parent->next; | ||
| 166 | new_vm = vm1; | ||
| 167 | |||
| 168 | parent->size -= size; | ||
| 169 | parent->next = vm1; | ||
| 170 | } else { | ||
| 171 | /* Allocate two new vm_structs for the new child and | ||
| 172 | * uppermost remainder, and use existing parent one for the | ||
| 173 | * lower remainder of parent range | ||
| 174 | */ | ||
| 175 | vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); | ||
| 176 | if (vm2 == NULL) { | ||
| 177 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
| 178 | kfree(vm1); | ||
| 179 | return NULL; | ||
| 180 | } | ||
| 181 | |||
| 182 | vm1->size = size; | ||
| 183 | vm1->addr = (void *) v_addr; | ||
| 184 | vm1->next = vm2; | ||
| 185 | new_vm = vm1; | ||
| 186 | |||
| 187 | vm2->size = ((unsigned long) parent->addr + parent->size) - | ||
| 188 | (v_addr + size); | ||
| 189 | vm2->addr = (void *) v_addr + size; | ||
| 190 | vm2->next = parent->next; | ||
| 191 | |||
| 192 | parent->size = v_addr - (unsigned long) parent->addr; | ||
| 193 | parent->next = vm1; | ||
| 194 | } | ||
| 195 | |||
| 196 | return new_vm; | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct vm_struct * __add_new_im_area(unsigned long req_addr, | ||
| 200 | unsigned long size) | ||
| 201 | { | ||
| 202 | struct vm_struct **p, *tmp, *area; | ||
| 203 | |||
| 204 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
| 205 | if (req_addr + size <= (unsigned long)tmp->addr) | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | |||
| 209 | area = kmalloc(sizeof(*area), GFP_KERNEL); | ||
| 210 | if (!area) | ||
| 211 | return NULL; | ||
| 212 | area->flags = 0; | ||
| 213 | area->addr = (void *)req_addr; | ||
| 214 | area->size = size; | ||
| 215 | area->next = *p; | ||
| 216 | *p = area; | ||
| 217 | |||
| 218 | return area; | ||
| 219 | } | ||
| 220 | |||
| 221 | static struct vm_struct * __im_get_area(unsigned long req_addr, | ||
| 222 | unsigned long size, | ||
| 223 | int criteria) | ||
| 224 | { | ||
| 225 | struct vm_struct *tmp; | ||
| 226 | int status; | ||
| 227 | |||
| 228 | status = im_region_status(req_addr, size, &tmp); | ||
| 229 | if ((criteria & status) == 0) { | ||
| 230 | return NULL; | ||
| 231 | } | ||
| 232 | |||
| 233 | switch (status) { | ||
| 234 | case IM_REGION_UNUSED: | ||
| 235 | tmp = __add_new_im_area(req_addr, size); | ||
| 236 | break; | ||
| 237 | case IM_REGION_SUBSET: | ||
| 238 | tmp = split_im_region(req_addr, size, tmp); | ||
| 239 | break; | ||
| 240 | case IM_REGION_EXISTS: | ||
| 241 | /* Return requested region */ | ||
| 242 | break; | ||
| 243 | case IM_REGION_SUPERSET: | ||
| 244 | /* Return first existing subset of requested region */ | ||
| 245 | break; | ||
| 246 | default: | ||
| 247 | printk(KERN_ERR "%s() unexpected imalloc region status\n", | ||
| 248 | __FUNCTION__); | ||
| 249 | tmp = NULL; | ||
| 250 | } | ||
| 251 | |||
| 252 | return tmp; | ||
| 253 | } | ||
| 254 | |||
| 255 | struct vm_struct * im_get_free_area(unsigned long size) | ||
| 256 | { | ||
| 257 | struct vm_struct *area; | ||
| 258 | unsigned long addr; | ||
| 259 | |||
| 260 | mutex_lock(&imlist_mutex); | ||
| 261 | if (get_free_im_addr(size, &addr)) { | ||
| 262 | printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", | ||
| 263 | __FUNCTION__, size); | ||
| 264 | area = NULL; | ||
| 265 | goto next_im_done; | ||
| 266 | } | ||
| 267 | |||
| 268 | area = __im_get_area(addr, size, IM_REGION_UNUSED); | ||
| 269 | if (area == NULL) { | ||
| 270 | printk(KERN_ERR | ||
| 271 | "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", | ||
| 272 | __FUNCTION__, addr, size); | ||
| 273 | } | ||
| 274 | next_im_done: | ||
| 275 | mutex_unlock(&imlist_mutex); | ||
| 276 | return area; | ||
| 277 | } | ||
| 278 | |||
| 279 | struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 280 | int criteria) | ||
| 281 | { | ||
| 282 | struct vm_struct *area; | ||
| 283 | |||
| 284 | mutex_lock(&imlist_mutex); | ||
| 285 | area = __im_get_area(v_addr, size, criteria); | ||
| 286 | mutex_unlock(&imlist_mutex); | ||
| 287 | return area; | ||
| 288 | } | ||
| 289 | |||
| 290 | void im_free(void * addr) | ||
| 291 | { | ||
| 292 | struct vm_struct **p, *tmp; | ||
| 293 | |||
| 294 | if (!addr) | ||
| 295 | return; | ||
| 296 | if ((unsigned long) addr & ~PAGE_MASK) { | ||
| 297 | printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | mutex_lock(&imlist_mutex); | ||
| 301 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | ||
| 302 | if (tmp->addr == addr) { | ||
| 303 | *p = tmp->next; | ||
| 304 | unmap_vm_area(tmp); | ||
| 305 | kfree(tmp); | ||
| 306 | mutex_unlock(&imlist_mutex); | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | mutex_unlock(&imlist_mutex); | ||
| 311 | printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, | ||
| 312 | addr); | ||
| 313 | } | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 5fce6ccecb8d..e1f5ded851f6 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
| 8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 9 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
| 10 | * | 9 | * |
| 11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 7312a265545f..1d6edf724c85 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
| 8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 9 | * | 8 | * |
| 10 | * Derived from "arch/i386/mm/init.c" | 9 | * Derived from "arch/i386/mm/init.c" |
| 11 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 10 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 0266a94d83b6..f0e7eedb1ba3 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
| 8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 9 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
| 10 | * | 9 | * |
| 11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
| @@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) | |||
| 129 | zone = pgdata->node_zones; | 128 | zone = pgdata->node_zones; |
| 130 | 129 | ||
| 131 | return __add_pages(zone, start_pfn, nr_pages); | 130 | return __add_pages(zone, start_pfn, nr_pages); |
| 132 | |||
| 133 | return 0; | ||
| 134 | } | 131 | } |
| 135 | 132 | ||
| 136 | /* | 133 | /* |
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c index 792086b01000..cc32ba41d900 100644 --- a/arch/powerpc/mm/mmu_context_32.c +++ b/arch/powerpc/mm/mmu_context_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 2558c34eedaa..c94a64fd3c01 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -40,8 +39,8 @@ extern int __map_without_bats; | |||
| 40 | extern unsigned long ioremap_base; | 39 | extern unsigned long ioremap_base; |
| 41 | extern unsigned int rtas_data, rtas_size; | 40 | extern unsigned int rtas_data, rtas_size; |
| 42 | 41 | ||
| 43 | struct _PTE; | 42 | struct hash_pte; |
| 44 | extern struct _PTE *Hash, *Hash_end; | 43 | extern struct hash_pte *Hash, *Hash_end; |
| 45 | extern unsigned long Hash_size, Hash_mask; | 44 | extern unsigned long Hash_size, Hash_mask; |
| 46 | 45 | ||
| 47 | extern unsigned int num_tlbcam_entries; | 46 | extern unsigned int num_tlbcam_entries; |
| @@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va, | |||
| 90 | else | 89 | else |
| 91 | _tlbie(va); | 90 | _tlbie(va); |
| 92 | } | 91 | } |
| 93 | #else /* CONFIG_PPC64 */ | ||
| 94 | /* imalloc region types */ | ||
| 95 | #define IM_REGION_UNUSED 0x1 | ||
| 96 | #define IM_REGION_SUBSET 0x2 | ||
| 97 | #define IM_REGION_EXISTS 0x4 | ||
| 98 | #define IM_REGION_OVERLAP 0x8 | ||
| 99 | #define IM_REGION_SUPERSET 0x10 | ||
| 100 | |||
| 101 | extern struct vm_struct * im_get_free_area(unsigned long size); | ||
| 102 | extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 103 | int region_type); | ||
| 104 | extern void im_free(void *addr); | ||
| 105 | #endif | 92 | #endif |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f6ae1a57d652..64488723162a 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -37,7 +36,6 @@ | |||
| 37 | unsigned long ioremap_base; | 36 | unsigned long ioremap_base; |
| 38 | unsigned long ioremap_bot; | 37 | unsigned long ioremap_bot; |
| 39 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | 38 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ |
| 40 | int io_bat_index; | ||
| 41 | 39 | ||
| 42 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 40 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) |
| 43 | #define HAVE_BATS 1 | 41 | #define HAVE_BATS 1 |
| @@ -300,51 +298,6 @@ void __init mapin_ram(void) | |||
| 300 | } | 298 | } |
| 301 | } | 299 | } |
| 302 | 300 | ||
| 303 | /* is x a power of 4? */ | ||
| 304 | #define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1) | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Set up a mapping for a block of I/O. | ||
| 308 | * virt, phys, size must all be page-aligned. | ||
| 309 | * This should only be called before ioremap is called. | ||
| 310 | */ | ||
| 311 | void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | ||
| 312 | unsigned int size, int flags) | ||
| 313 | { | ||
| 314 | int i; | ||
| 315 | |||
| 316 | if (virt > KERNELBASE && virt < ioremap_bot) | ||
| 317 | ioremap_bot = ioremap_base = virt; | ||
| 318 | |||
| 319 | #ifdef HAVE_BATS | ||
| 320 | /* | ||
| 321 | * Use a BAT for this if possible... | ||
| 322 | */ | ||
| 323 | if (io_bat_index < 2 && is_power_of_2(size) | ||
| 324 | && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||
| 325 | setbat(io_bat_index, virt, phys, size, flags); | ||
| 326 | ++io_bat_index; | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | #endif /* HAVE_BATS */ | ||
| 330 | |||
| 331 | #ifdef HAVE_TLBCAM | ||
| 332 | /* | ||
| 333 | * Use a CAM for this if possible... | ||
| 334 | */ | ||
| 335 | if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) | ||
| 336 | && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||
| 337 | settlbcam(tlbcam_index, virt, phys, size, flags, 0); | ||
| 338 | ++tlbcam_index; | ||
| 339 | return; | ||
| 340 | } | ||
| 341 | #endif /* HAVE_TLBCAM */ | ||
| 342 | |||
| 343 | /* No BATs available, put it in the page tables. */ | ||
| 344 | for (i = 0; i < size; i += PAGE_SIZE) | ||
| 345 | map_page(virt + i, phys + i, flags); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Scan the real Linux page tables and return a PTE pointer for | 301 | /* Scan the real Linux page tables and return a PTE pointer for |
| 349 | * a virtual address in a context. | 302 | * a virtual address in a context. |
| 350 | * Returns true (1) if PTE was found, zero otherwise. The pointer to | 303 | * Returns true (1) if PTE was found, zero otherwise. The pointer to |
| @@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) | |||
| 379 | return(retval); | 332 | return(retval); |
| 380 | } | 333 | } |
| 381 | 334 | ||
| 382 | /* Find physical address for this virtual address. Normally used by | ||
| 383 | * I/O functions, but anyone can call it. | ||
| 384 | */ | ||
| 385 | unsigned long iopa(unsigned long addr) | ||
| 386 | { | ||
| 387 | unsigned long pa; | ||
| 388 | |||
| 389 | /* I don't know why this won't work on PMacs or CHRP. It | ||
| 390 | * appears there is some bug, or there is some implicit | ||
| 391 | * mapping done not properly represented by BATs or in page | ||
| 392 | * tables.......I am actively working on resolving this, but | ||
| 393 | * can't hold up other stuff. -- Dan | ||
| 394 | */ | ||
| 395 | pte_t *pte; | ||
| 396 | struct mm_struct *mm; | ||
| 397 | |||
| 398 | /* Check the BATs */ | ||
| 399 | pa = v_mapped_by_bats(addr); | ||
| 400 | if (pa) | ||
| 401 | return pa; | ||
| 402 | |||
| 403 | /* Allow mapping of user addresses (within the thread) | ||
| 404 | * for DMA if necessary. | ||
| 405 | */ | ||
| 406 | if (addr < TASK_SIZE) | ||
| 407 | mm = current->mm; | ||
| 408 | else | ||
| 409 | mm = &init_mm; | ||
| 410 | |||
| 411 | pa = 0; | ||
| 412 | if (get_pteptr(mm, addr, &pte, NULL)) { | ||
| 413 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | ||
| 414 | pte_unmap(pte); | ||
| 415 | } | ||
| 416 | |||
| 417 | return(pa); | ||
| 418 | } | ||
| 419 | |||
| 420 | /* This is will find the virtual address for a physical one.... | ||
| 421 | * Swiped from APUS, could be dangerous :-). | ||
| 422 | * This is only a placeholder until I really find a way to make this | ||
| 423 | * work. -- Dan | ||
| 424 | */ | ||
| 425 | unsigned long | ||
| 426 | mm_ptov (unsigned long paddr) | ||
| 427 | { | ||
| 428 | unsigned long ret; | ||
| 429 | #if 0 | ||
| 430 | if (paddr < 16*1024*1024) | ||
| 431 | ret = ZTWO_VADDR(paddr); | ||
| 432 | else { | ||
| 433 | int i; | ||
| 434 | |||
| 435 | for (i = 0; i < kmap_chunk_count;){ | ||
| 436 | unsigned long phys = kmap_chunks[i++]; | ||
| 437 | unsigned long size = kmap_chunks[i++]; | ||
| 438 | unsigned long virt = kmap_chunks[i++]; | ||
| 439 | if (paddr >= phys | ||
| 440 | && paddr < (phys + size)){ | ||
| 441 | ret = virt + paddr - phys; | ||
| 442 | goto exit; | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | ret = (unsigned long) __va(paddr); | ||
| 447 | } | ||
| 448 | exit: | ||
| 449 | #ifdef DEBUGPV | ||
| 450 | printk ("PTOV(%lx)=%lx\n", paddr, ret); | ||
| 451 | #endif | ||
| 452 | #else | ||
| 453 | ret = (unsigned long)paddr + KERNELBASE; | ||
| 454 | #endif | ||
| 455 | return ret; | ||
| 456 | } | ||
| 457 | |||
| 458 | #ifdef CONFIG_DEBUG_PAGEALLOC | 335 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 459 | 336 | ||
| 460 | static int __change_page_attr(struct page *page, pgprot_t prot) | 337 | static int __change_page_attr(struct page *page, pgprot_t prot) |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index ad6e135bf212..3dfd10db931a 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) | 7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) |
| 8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 9 | * Copyright (C) 1996 Paul Mackerras | 9 | * Copyright (C) 1996 Paul Mackerras |
| 10 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 11 | * | 10 | * |
| 12 | * Derived from "arch/i386/mm/init.c" | 11 | * Derived from "arch/i386/mm/init.c" |
| 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 12 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -34,41 +33,27 @@ | |||
| 34 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
| 35 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
| 36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/bootmem.h> | ||
| 39 | #include <linux/highmem.h> | ||
| 40 | #include <linux/idr.h> | ||
| 41 | #include <linux/nodemask.h> | ||
| 42 | #include <linux/module.h> | ||
| 43 | 36 | ||
| 44 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
| 45 | #include <asm/page.h> | 38 | #include <asm/page.h> |
| 46 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 47 | #include <asm/lmb.h> | ||
| 48 | #include <asm/rtas.h> | ||
| 49 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 50 | #include <asm/mmu_context.h> | 41 | #include <asm/mmu_context.h> |
| 51 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 52 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
| 53 | #include <asm/uaccess.h> | ||
| 54 | #include <asm/smp.h> | 44 | #include <asm/smp.h> |
| 55 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
| 56 | #include <asm/tlb.h> | 46 | #include <asm/tlb.h> |
| 57 | #include <asm/eeh.h> | ||
| 58 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
| 59 | #include <asm/mmzone.h> | ||
| 60 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
| 61 | #include <asm/sections.h> | 49 | #include <asm/sections.h> |
| 62 | #include <asm/system.h> | 50 | #include <asm/system.h> |
| 63 | #include <asm/iommu.h> | ||
| 64 | #include <asm/abs_addr.h> | 51 | #include <asm/abs_addr.h> |
| 65 | #include <asm/vdso.h> | ||
| 66 | #include <asm/firmware.h> | 52 | #include <asm/firmware.h> |
| 67 | 53 | ||
| 68 | #include "mmu_decl.h" | 54 | #include "mmu_decl.h" |
| 69 | 55 | ||
| 70 | unsigned long ioremap_bot = IMALLOC_BASE; | 56 | unsigned long ioremap_bot = IOREMAP_BASE; |
| 71 | static unsigned long phbs_io_bot = PHBS_IO_BASE; | ||
| 72 | 57 | ||
| 73 | /* | 58 | /* |
| 74 | * map_io_page currently only called by __ioremap | 59 | * map_io_page currently only called by __ioremap |
| @@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
| 102 | * entry in the hardware page table. | 87 | * entry in the hardware page table. |
| 103 | * | 88 | * |
| 104 | */ | 89 | */ |
| 105 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 90 | if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE, |
| 106 | mmu_io_psize)) { | 91 | pa, flags, mmu_io_psize)) { |
| 107 | printk(KERN_ERR "Failed to do bolted mapping IO " | 92 | printk(KERN_ERR "Failed to do bolted mapping IO " |
| 108 | "memory at %016lx !\n", pa); | 93 | "memory at %016lx !\n", pa); |
| 109 | return -ENOMEM; | 94 | return -ENOMEM; |
| @@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
| 113 | } | 98 | } |
| 114 | 99 | ||
| 115 | 100 | ||
| 116 | static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | 101 | /** |
| 117 | unsigned long ea, unsigned long size, | 102 | * __ioremap_at - Low level function to establish the page tables |
| 103 | * for an IO mapping | ||
| 104 | */ | ||
| 105 | void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | ||
| 118 | unsigned long flags) | 106 | unsigned long flags) |
| 119 | { | 107 | { |
| 120 | unsigned long i; | 108 | unsigned long i; |
| @@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | |||
| 122 | if ((flags & _PAGE_PRESENT) == 0) | 110 | if ((flags & _PAGE_PRESENT) == 0) |
| 123 | flags |= pgprot_val(PAGE_KERNEL); | 111 | flags |= pgprot_val(PAGE_KERNEL); |
| 124 | 112 | ||
| 113 | WARN_ON(pa & ~PAGE_MASK); | ||
| 114 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
| 115 | WARN_ON(size & ~PAGE_MASK); | ||
| 116 | |||
| 125 | for (i = 0; i < size; i += PAGE_SIZE) | 117 | for (i = 0; i < size; i += PAGE_SIZE) |
| 126 | if (map_io_page(ea+i, pa+i, flags)) | 118 | if (map_io_page((unsigned long)ea+i, pa+i, flags)) |
| 127 | return NULL; | 119 | return NULL; |
| 128 | 120 | ||
| 129 | return (void __iomem *) (ea + (addr & ~PAGE_MASK)); | 121 | return (void __iomem *)ea; |
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * __iounmap_from - Low level function to tear down the page tables | ||
| 126 | * for an IO mapping. This is used for mappings that | ||
| 127 | * are manipulated manually, like partial unmapping of | ||
| 128 | * PCI IOs or ISA space. | ||
| 129 | */ | ||
| 130 | void __iounmap_at(void *ea, unsigned long size) | ||
| 131 | { | ||
| 132 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
| 133 | WARN_ON(size & ~PAGE_MASK); | ||
| 134 | |||
| 135 | unmap_kernel_range((unsigned long)ea, size); | ||
| 130 | } | 136 | } |
| 131 | 137 | ||
| 132 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | 138 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, |
| 133 | unsigned long flags) | 139 | unsigned long flags) |
| 134 | { | 140 | { |
| 135 | unsigned long pa, ea; | 141 | phys_addr_t paligned; |
| 136 | void __iomem *ret; | 142 | void __iomem *ret; |
| 137 | 143 | ||
| 138 | /* | 144 | /* |
| @@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | |||
| 144 | * IMALLOC_END | 150 | * IMALLOC_END |
| 145 | * | 151 | * |
| 146 | */ | 152 | */ |
| 147 | pa = addr & PAGE_MASK; | 153 | paligned = addr & PAGE_MASK; |
| 148 | size = PAGE_ALIGN(addr + size) - pa; | 154 | size = PAGE_ALIGN(addr + size) - paligned; |
| 149 | 155 | ||
| 150 | if ((size == 0) || (pa == 0)) | 156 | if ((size == 0) || (paligned == 0)) |
| 151 | return NULL; | 157 | return NULL; |
| 152 | 158 | ||
| 153 | if (mem_init_done) { | 159 | if (mem_init_done) { |
| 154 | struct vm_struct *area; | 160 | struct vm_struct *area; |
| 155 | area = im_get_free_area(size); | 161 | |
| 162 | area = __get_vm_area(size, VM_IOREMAP, | ||
| 163 | ioremap_bot, IOREMAP_END); | ||
| 156 | if (area == NULL) | 164 | if (area == NULL) |
| 157 | return NULL; | 165 | return NULL; |
| 158 | ea = (unsigned long)(area->addr); | 166 | ret = __ioremap_at(paligned, area->addr, size, flags); |
| 159 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
| 160 | if (!ret) | 167 | if (!ret) |
| 161 | im_free(area->addr); | 168 | vunmap(area->addr); |
| 162 | } else { | 169 | } else { |
| 163 | ea = ioremap_bot; | 170 | ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); |
| 164 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
| 165 | if (ret) | 171 | if (ret) |
| 166 | ioremap_bot += size; | 172 | ioremap_bot += size; |
| 167 | } | 173 | } |
| 174 | |||
| 175 | if (ret) | ||
| 176 | ret += addr & ~PAGE_MASK; | ||
| 168 | return ret; | 177 | return ret; |
| 169 | } | 178 | } |
| 170 | 179 | ||
| @@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, | |||
| 187 | } | 196 | } |
| 188 | 197 | ||
| 189 | 198 | ||
| 190 | #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) | ||
| 191 | |||
| 192 | int __ioremap_explicit(phys_addr_t pa, unsigned long ea, | ||
| 193 | unsigned long size, unsigned long flags) | ||
| 194 | { | ||
| 195 | struct vm_struct *area; | ||
| 196 | void __iomem *ret; | ||
| 197 | |||
| 198 | /* For now, require page-aligned values for pa, ea, and size */ | ||
| 199 | if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || | ||
| 200 | !IS_PAGE_ALIGNED(size)) { | ||
| 201 | printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__); | ||
| 202 | return 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (!mem_init_done) { | ||
| 206 | /* Two things to consider in this case: | ||
| 207 | * 1) No records will be kept (imalloc, etc) that the region | ||
| 208 | * has been remapped | ||
| 209 | * 2) It won't be easy to iounmap() the region later (because | ||
| 210 | * of 1) | ||
| 211 | */ | ||
| 212 | ; | ||
| 213 | } else { | ||
| 214 | area = im_get_area(ea, size, | ||
| 215 | IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); | ||
| 216 | if (area == NULL) { | ||
| 217 | /* Expected when PHB-dlpar is in play */ | ||
| 218 | return 1; | ||
| 219 | } | ||
| 220 | if (ea != (unsigned long) area->addr) { | ||
| 221 | printk(KERN_ERR "unexpected addr return from " | ||
| 222 | "im_get_area\n"); | ||
| 223 | return 1; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | ret = __ioremap_com(pa, pa, ea, size, flags); | ||
| 228 | if (ret == NULL) { | ||
| 229 | printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); | ||
| 230 | return 1; | ||
| 231 | } | ||
| 232 | if (ret != (void *) ea) { | ||
| 233 | printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); | ||
| 234 | return 1; | ||
| 235 | } | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | 199 | /* |
| 241 | * Unmap an IO region and remove it from imalloc'd list. | 200 | * Unmap an IO region and remove it from imalloc'd list. |
| 242 | * Access to IO memory should be serialized by driver. | 201 | * Access to IO memory should be serialized by driver. |
| 243 | * This code is modeled after vmalloc code - unmap_vm_area() | ||
| 244 | * | ||
| 245 | * XXX what about calls before mem_init_done (ie python_countermeasures()) | ||
| 246 | */ | 202 | */ |
| 247 | void __iounmap(volatile void __iomem *token) | 203 | void __iounmap(volatile void __iomem *token) |
| 248 | { | 204 | { |
| @@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token) | |||
| 251 | if (!mem_init_done) | 207 | if (!mem_init_done) |
| 252 | return; | 208 | return; |
| 253 | 209 | ||
| 254 | addr = (void *) ((unsigned long __force) token & PAGE_MASK); | 210 | addr = (void *) ((unsigned long __force) |
| 255 | 211 | PCI_FIX_ADDR(token) & PAGE_MASK); | |
| 256 | im_free(addr); | 212 | if ((unsigned long)addr < ioremap_bot) { |
| 213 | printk(KERN_WARNING "Attempt to iounmap early bolted mapping" | ||
| 214 | " at 0x%p\n", addr); | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | vunmap(addr); | ||
| 257 | } | 218 | } |
| 258 | 219 | ||
| 259 | void iounmap(volatile void __iomem *token) | 220 | void iounmap(volatile void __iomem *token) |
| @@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token) | |||
| 264 | __iounmap(token); | 225 | __iounmap(token); |
| 265 | } | 226 | } |
| 266 | 227 | ||
| 267 | static int iounmap_subset_regions(unsigned long addr, unsigned long size) | ||
| 268 | { | ||
| 269 | struct vm_struct *area; | ||
| 270 | |||
| 271 | /* Check whether subsets of this region exist */ | ||
| 272 | area = im_get_area(addr, size, IM_REGION_SUPERSET); | ||
| 273 | if (area == NULL) | ||
| 274 | return 1; | ||
| 275 | |||
| 276 | while (area) { | ||
| 277 | iounmap((void __iomem *) area->addr); | ||
| 278 | area = im_get_area(addr, size, | ||
| 279 | IM_REGION_SUPERSET); | ||
| 280 | } | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | int __iounmap_explicit(volatile void __iomem *start, unsigned long size) | ||
| 286 | { | ||
| 287 | struct vm_struct *area; | ||
| 288 | unsigned long addr; | ||
| 289 | int rc; | ||
| 290 | |||
| 291 | addr = (unsigned long __force) start & PAGE_MASK; | ||
| 292 | |||
| 293 | /* Verify that the region either exists or is a subset of an existing | ||
| 294 | * region. In the latter case, split the parent region to create | ||
| 295 | * the exact region | ||
| 296 | */ | ||
| 297 | area = im_get_area(addr, size, | ||
| 298 | IM_REGION_EXISTS | IM_REGION_SUBSET); | ||
| 299 | if (area == NULL) { | ||
| 300 | /* Determine whether subset regions exist. If so, unmap */ | ||
| 301 | rc = iounmap_subset_regions(addr, size); | ||
| 302 | if (rc) { | ||
| 303 | printk(KERN_ERR | ||
| 304 | "%s() cannot unmap nonexistent range 0x%lx\n", | ||
| 305 | __FUNCTION__, addr); | ||
| 306 | return 1; | ||
| 307 | } | ||
| 308 | } else { | ||
| 309 | iounmap((void __iomem *) area->addr); | ||
| 310 | } | ||
| 311 | /* | ||
| 312 | * FIXME! This can't be right: | ||
| 313 | iounmap(area->addr); | ||
| 314 | * Maybe it should be "iounmap(area);" | ||
| 315 | */ | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | EXPORT_SYMBOL(ioremap); | 228 | EXPORT_SYMBOL(ioremap); |
| 320 | EXPORT_SYMBOL(ioremap_flags); | 229 | EXPORT_SYMBOL(ioremap_flags); |
| 321 | EXPORT_SYMBOL(__ioremap); | 230 | EXPORT_SYMBOL(__ioremap); |
| 322 | EXPORT_SYMBOL(iounmap); | 231 | EXPORT_SYMBOL(iounmap); |
| 323 | EXPORT_SYMBOL(__iounmap); | 232 | EXPORT_SYMBOL(__iounmap); |
| 324 | |||
| 325 | static DEFINE_SPINLOCK(phb_io_lock); | ||
| 326 | |||
| 327 | void __iomem * reserve_phb_iospace(unsigned long size) | ||
| 328 | { | ||
| 329 | void __iomem *virt_addr; | ||
| 330 | |||
| 331 | if (phbs_io_bot >= IMALLOC_BASE) | ||
| 332 | panic("reserve_phb_iospace(): phb io space overflow\n"); | ||
| 333 | |||
| 334 | spin_lock(&phb_io_lock); | ||
| 335 | virt_addr = (void __iomem *) phbs_io_bot; | ||
| 336 | phbs_io_bot += size; | ||
| 337 | spin_unlock(&phb_io_lock); | ||
| 338 | |||
| 339 | return virt_addr; | ||
| 340 | } | ||
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ec1421a20aaa..5c45d474cfcc 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -35,12 +34,12 @@ | |||
| 35 | 34 | ||
| 36 | #include "mmu_decl.h" | 35 | #include "mmu_decl.h" |
| 37 | 36 | ||
| 38 | PTE *Hash, *Hash_end; | 37 | struct hash_pte *Hash, *Hash_end; |
| 39 | unsigned long Hash_size, Hash_mask; | 38 | unsigned long Hash_size, Hash_mask; |
| 40 | unsigned long _SDR1; | 39 | unsigned long _SDR1; |
| 41 | 40 | ||
| 42 | union ubat { /* BAT register values to be loaded */ | 41 | union ubat { /* BAT register values to be loaded */ |
| 43 | BAT bat; | 42 | struct ppc_bat bat; |
| 44 | u32 word[2]; | 43 | u32 word[2]; |
| 45 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ | 44 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ |
| 46 | 45 | ||
| @@ -245,7 +244,7 @@ void __init MMU_init_hw(void) | |||
| 245 | cacheable_memzero(Hash, Hash_size); | 244 | cacheable_memzero(Hash, Hash_size); |
| 246 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; | 245 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; |
| 247 | 246 | ||
| 248 | Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); | 247 | Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); |
| 249 | 248 | ||
| 250 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", | 249 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", |
| 251 | total_memory >> 20, Hash_size >> 10, Hash); | 250 | total_memory >> 20, Hash_size >> 10, Hash); |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 132c6bc66ce1..28492bbdee8e 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
| @@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
| 55 | for (entry = 0; entry < 8; entry++, ste++) { | 55 | for (entry = 0; entry < 8; entry++, ste++) { |
| 56 | if (!(ste->esid_data & STE_ESID_V)) { | 56 | if (!(ste->esid_data & STE_ESID_V)) { |
| 57 | ste->vsid_data = vsid_data; | 57 | ste->vsid_data = vsid_data; |
| 58 | asm volatile("eieio":::"memory"); | 58 | eieio(); |
| 59 | ste->esid_data = esid_data; | 59 | ste->esid_data = esid_data; |
| 60 | return (global_entry | entry); | 60 | return (global_entry | entry); |
| 61 | } | 61 | } |
| @@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
| 101 | asm volatile("sync" : : : "memory"); /* Order update */ | 101 | asm volatile("sync" : : : "memory"); /* Order update */ |
| 102 | 102 | ||
| 103 | castout_ste->vsid_data = vsid_data; | 103 | castout_ste->vsid_data = vsid_data; |
| 104 | asm volatile("eieio" : : : "memory"); /* Order update */ | 104 | eieio(); /* Order update */ |
| 105 | castout_ste->esid_data = esid_data; | 105 | castout_ste->esid_data = esid_data; |
| 106 | 106 | ||
| 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); | 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); |
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index 6a69417cbc0e..06c7e77e097a 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index 2bfc4d7e1aa2..cbd34fc813ee 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -239,3 +238,59 @@ void pte_free_finish(void) | |||
| 239 | pte_free_submit(*batchp); | 238 | pte_free_submit(*batchp); |
| 240 | *batchp = NULL; | 239 | *batchp = NULL; |
| 241 | } | 240 | } |
| 241 | |||
| 242 | /** | ||
| 243 | * __flush_hash_table_range - Flush all HPTEs for a given address range | ||
| 244 | * from the hash table (and the TLB). But keeps | ||
| 245 | * the linux PTEs intact. | ||
| 246 | * | ||
| 247 | * @mm : mm_struct of the target address space (generally init_mm) | ||
| 248 | * @start : starting address | ||
| 249 | * @end : ending address (not included in the flush) | ||
| 250 | * | ||
| 251 | * This function is mostly to be used by some IO hotplug code in order | ||
| 252 | * to remove all hash entries from a given address range used to map IO | ||
| 253 | * space on a removed PCI-PCI bidge without tearing down the full mapping | ||
| 254 | * since 64K pages may overlap with other bridges when using 64K pages | ||
| 255 | * with 4K HW pages on IO space. | ||
| 256 | * | ||
| 257 | * Because of that usage pattern, it's only available with CONFIG_HOTPLUG | ||
| 258 | * and is implemented for small size rather than speed. | ||
| 259 | */ | ||
| 260 | #ifdef CONFIG_HOTPLUG | ||
| 261 | |||
| 262 | void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | ||
| 263 | unsigned long end) | ||
| 264 | { | ||
| 265 | unsigned long flags; | ||
| 266 | |||
| 267 | start = _ALIGN_DOWN(start, PAGE_SIZE); | ||
| 268 | end = _ALIGN_UP(end, PAGE_SIZE); | ||
| 269 | |||
| 270 | BUG_ON(!mm->pgd); | ||
| 271 | |||
| 272 | /* Note: Normally, we should only ever use a batch within a | ||
| 273 | * PTE locked section. This violates the rule, but will work | ||
| 274 | * since we don't actually modify the PTEs, we just flush the | ||
| 275 | * hash while leaving the PTEs intact (including their reference | ||
| 276 | * to being hashed). This is not the most performance oriented | ||
| 277 | * way to do things but is fine for our needs here. | ||
| 278 | */ | ||
| 279 | local_irq_save(flags); | ||
| 280 | arch_enter_lazy_mmu_mode(); | ||
| 281 | for (; start < end; start += PAGE_SIZE) { | ||
| 282 | pte_t *ptep = find_linux_pte(mm->pgd, start); | ||
| 283 | unsigned long pte; | ||
| 284 | |||
| 285 | if (ptep == NULL) | ||
| 286 | continue; | ||
| 287 | pte = pte_val(*ptep); | ||
| 288 | if (!(pte & _PAGE_HASHPTE)) | ||
| 289 | continue; | ||
| 290 | hpte_need_flush(mm, start, ptep, pte, 0); | ||
| 291 | } | ||
| 292 | arch_leave_lazy_mmu_mode(); | ||
| 293 | local_irq_restore(flags); | ||
| 294 | } | ||
| 295 | |||
| 296 | #endif /* CONFIG_HOTPLUG */ | ||
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index fe597a154d4f..a7c206b665af 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | 2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM |
| 3 | * Added mmcra[slot] support: | ||
| 4 | * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM | ||
| 3 | * | 5 | * |
| 4 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
| @@ -181,11 +183,17 @@ static void __attribute_used__ kernel_unknown_bucket(void) | |||
| 181 | * On GQ and newer the MMCRA stores the HV and PR bits at the time | 183 | * On GQ and newer the MMCRA stores the HV and PR bits at the time |
| 182 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in | 184 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in |
| 183 | * the hypervisor, our exception vectors or RTAS. | 185 | * the hypervisor, our exception vectors or RTAS. |
| 186 | * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits | ||
| 187 | * to more accurately identify the address of the sampled instruction. The | ||
| 188 | * mmcra[slot] bits represent the slot number of a sampled instruction | ||
| 189 | * within an instruction group. The slot will contain a value between 1 | ||
| 190 | * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0. | ||
| 184 | */ | 191 | */ |
| 185 | static unsigned long get_pc(struct pt_regs *regs) | 192 | static unsigned long get_pc(struct pt_regs *regs) |
| 186 | { | 193 | { |
| 187 | unsigned long pc = mfspr(SPRN_SIAR); | 194 | unsigned long pc = mfspr(SPRN_SIAR); |
| 188 | unsigned long mmcra; | 195 | unsigned long mmcra; |
| 196 | unsigned long slot; | ||
| 189 | 197 | ||
| 190 | /* Cant do much about it */ | 198 | /* Cant do much about it */ |
| 191 | if (!cur_cpu_spec->oprofile_mmcra_sihv) | 199 | if (!cur_cpu_spec->oprofile_mmcra_sihv) |
| @@ -193,6 +201,12 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
| 193 | 201 | ||
| 194 | mmcra = mfspr(SPRN_MMCRA); | 202 | mmcra = mfspr(SPRN_MMCRA); |
| 195 | 203 | ||
| 204 | if (mmcra & MMCRA_SAMPLE_ENABLE) { | ||
| 205 | slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT); | ||
| 206 | if (slot > 1) | ||
| 207 | pc += 4 * (slot - 1); | ||
| 208 | } | ||
| 209 | |||
| 196 | /* Were we in the hypervisor? */ | 210 | /* Were we in the hypervisor? */ |
| 197 | if (firmware_has_feature(FW_FEATURE_LPAR) && | 211 | if (firmware_has_feature(FW_FEATURE_LPAR) && |
| 198 | (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) | 212 | (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index f591a9fc19b9..4be6e7a17b66 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
| @@ -54,7 +54,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 54 | struct pci_controller *hose = bus->sysdata; | 54 | struct pci_controller *hose = bus->sysdata; |
| 55 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 55 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 56 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 56 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
| 57 | | (hose->index << 24); | 57 | | (hose->global_number << 24); |
| 58 | int ret = -1; | 58 | int ret = -1; |
| 59 | int rval; | 59 | int rval; |
| 60 | 60 | ||
| @@ -69,7 +69,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, | |||
| 69 | struct pci_controller *hose = bus->sysdata; | 69 | struct pci_controller *hose = bus->sysdata; |
| 70 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 70 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 71 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 71 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
| 72 | | (hose->index << 24); | 72 | | (hose->global_number << 24); |
| 73 | int rval; | 73 | int rval; |
| 74 | 74 | ||
| 75 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | 75 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, |
| @@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = { | |||
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | 85 | ||
| 86 | void __init efika_pcisetup(void) | 86 | static void __init efika_pcisetup(void) |
| 87 | { | 87 | { |
| 88 | const int *bus_range; | 88 | const int *bus_range; |
| 89 | int len; | 89 | int len; |
| @@ -128,7 +128,7 @@ void __init efika_pcisetup(void) | |||
| 128 | printk(" controlled by %s\n", pcictrl->full_name); | 128 | printk(" controlled by %s\n", pcictrl->full_name); |
| 129 | printk("\n"); | 129 | printk("\n"); |
| 130 | 130 | ||
| 131 | hose = pcibios_alloc_controller(); | 131 | hose = pcibios_alloc_controller(of_node_get(pcictrl)); |
| 132 | if (!hose) { | 132 | if (!hose) { |
| 133 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | 133 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
| 134 | ": Can't allocate PCI controller structure for %s\n", | 134 | ": Can't allocate PCI controller structure for %s\n", |
| @@ -136,7 +136,6 @@ void __init efika_pcisetup(void) | |||
| 136 | return; | 136 | return; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | hose->arch_data = of_node_get(pcictrl); | ||
| 140 | hose->first_busno = bus_range[0]; | 139 | hose->first_busno = bus_range[0]; |
| 141 | hose->last_busno = bus_range[1]; | 140 | hose->last_busno = bus_range[1]; |
| 142 | hose->ops = &rtas_pci_ops; | 141 | hose->ops = &rtas_pci_ops; |
| @@ -145,7 +144,7 @@ void __init efika_pcisetup(void) | |||
| 145 | } | 144 | } |
| 146 | 145 | ||
| 147 | #else | 146 | #else |
| 148 | void __init efika_pcisetup(void) | 147 | static void __init efika_pcisetup(void) |
| 149 | {} | 148 | {} |
| 150 | #endif | 149 | #endif |
| 151 | 150 | ||
| @@ -252,6 +251,8 @@ define_machine(efika) | |||
| 252 | .progress = rtas_progress, | 251 | .progress = rtas_progress, |
| 253 | .get_boot_time = rtas_get_boot_time, | 252 | .get_boot_time = rtas_get_boot_time, |
| 254 | .calibrate_decr = generic_calibrate_decr, | 253 | .calibrate_decr = generic_calibrate_decr, |
| 254 | #ifdef CONFIG_PCI | ||
| 255 | .phys_mem_access_prot = pci_phys_mem_access_prot, | 255 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
| 256 | #endif | ||
| 256 | }; | 257 | }; |
| 257 | 258 | ||
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 1cfc00dfb99a..5c46e898fd45 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c | |||
| @@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(void) | |||
| 156 | 156 | ||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | void lite5200_show_cpuinfo(struct seq_file *m) | 159 | static void lite5200_show_cpuinfo(struct seq_file *m) |
| 160 | { | 160 | { |
| 161 | struct device_node* np = of_find_all_nodes(NULL); | 161 | struct device_node* np = of_find_all_nodes(NULL); |
| 162 | const char *model = NULL; | 162 | const char *model = NULL; |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index 34d34a26d305..4c6c82a684b1 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c | |||
| @@ -112,18 +112,18 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
| 112 | u32 value; | 112 | u32 value; |
| 113 | 113 | ||
| 114 | if (ppc_md.pci_exclude_device) | 114 | if (ppc_md.pci_exclude_device) |
| 115 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 115 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
| 116 | return PCIBIOS_DEVICE_NOT_FOUND; | 116 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 117 | 117 | ||
| 118 | out_be32(hose->cfg_addr, | 118 | out_be32(hose->cfg_addr, |
| 119 | (1 << 31) | | 119 | (1 << 31) | |
| 120 | ((bus->number - hose->bus_offset) << 16) | | 120 | (bus->number << 16) | |
| 121 | (devfn << 8) | | 121 | (devfn << 8) | |
| 122 | (offset & 0xfc)); | 122 | (offset & 0xfc)); |
| 123 | mb(); | 123 | mb(); |
| 124 | 124 | ||
| 125 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) | 125 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) |
| 126 | if (bus->number != hose->bus_offset) { | 126 | if (bus->number) { |
| 127 | /* workaround for the bug 435 of the MPC5200 (L25R); | 127 | /* workaround for the bug 435 of the MPC5200 (L25R); |
| 128 | * Don't do 32 bits config access during type-1 cycles */ | 128 | * Don't do 32 bits config access during type-1 cycles */ |
| 129 | switch (len) { | 129 | switch (len) { |
| @@ -169,18 +169,18 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |||
| 169 | u32 value, mask; | 169 | u32 value, mask; |
| 170 | 170 | ||
| 171 | if (ppc_md.pci_exclude_device) | 171 | if (ppc_md.pci_exclude_device) |
| 172 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 172 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
| 173 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 174 | 174 | ||
| 175 | out_be32(hose->cfg_addr, | 175 | out_be32(hose->cfg_addr, |
| 176 | (1 << 31) | | 176 | (1 << 31) | |
| 177 | ((bus->number - hose->bus_offset) << 16) | | 177 | (bus->number << 16) | |
| 178 | (devfn << 8) | | 178 | (devfn << 8) | |
| 179 | (offset & 0xfc)); | 179 | (offset & 0xfc)); |
| 180 | mb(); | 180 | mb(); |
| 181 | 181 | ||
| 182 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) | 182 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) |
| 183 | if (bus->number != hose->bus_offset) { | 183 | if (bus->number) { |
| 184 | /* workaround for the bug 435 of the MPC5200 (L25R); | 184 | /* workaround for the bug 435 of the MPC5200 (L25R); |
| 185 | * Don't do 32 bits config access during type-1 cycles */ | 185 | * Don't do 32 bits config access during type-1 cycles */ |
| 186 | switch (len) { | 186 | switch (len) { |
| @@ -385,17 +385,13 @@ mpc52xx_add_bridge(struct device_node *node) | |||
| 385 | * tree are needed to configure the 52xx PCI controller. Rather | 385 | * tree are needed to configure the 52xx PCI controller. Rather |
| 386 | * than parse the tree here, let pci_process_bridge_OF_ranges() | 386 | * than parse the tree here, let pci_process_bridge_OF_ranges() |
| 387 | * do it for us and extract the values after the fact */ | 387 | * do it for us and extract the values after the fact */ |
| 388 | hose = pcibios_alloc_controller(); | 388 | hose = pcibios_alloc_controller(node); |
| 389 | if (!hose) | 389 | if (!hose) |
| 390 | return -ENOMEM; | 390 | return -ENOMEM; |
| 391 | 391 | ||
| 392 | hose->arch_data = node; | ||
| 393 | hose->set_cfg_type = 1; | ||
| 394 | |||
| 395 | hose->first_busno = bus_range ? bus_range[0] : 0; | 392 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 396 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 393 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 397 | 394 | ||
| 398 | hose->bus_offset = 0; | ||
| 399 | hose->ops = &mpc52xx_pci_ops; | 395 | hose->ops = &mpc52xx_pci_ops; |
| 400 | 396 | ||
| 401 | pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); | 397 | pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index fd40044d16cd..ee2e7639c63e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | /* these are defined in mpc52xx_sleep.S, and only used here */ | 11 | /* these are defined in mpc52xx_sleep.S, and only used here */ |
| 12 | extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs, | 12 | extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs, |
| 13 | struct mpc52xx_cdm *, struct mpc52xx_intr *); | 13 | struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*); |
| 14 | extern void mpc52xx_ds_sram(void); | 14 | extern void mpc52xx_ds_sram(void); |
| 15 | extern const long mpc52xx_ds_sram_size; | 15 | extern const long mpc52xx_ds_sram_size; |
| 16 | extern void mpc52xx_ds_cached(void); | 16 | extern void mpc52xx_ds_cached(void); |
| @@ -21,7 +21,7 @@ static void __iomem *sdram; | |||
| 21 | static struct mpc52xx_cdm __iomem *cdm; | 21 | static struct mpc52xx_cdm __iomem *cdm; |
| 22 | static struct mpc52xx_intr __iomem *intr; | 22 | static struct mpc52xx_intr __iomem *intr; |
| 23 | static struct mpc52xx_gpio_wkup __iomem *gpiow; | 23 | static struct mpc52xx_gpio_wkup __iomem *gpiow; |
| 24 | static void *sram; | 24 | static void __iomem *sram; |
| 25 | static int sram_size; | 25 | static int sram_size; |
| 26 | 26 | ||
| 27 | struct mpc52xx_suspend mpc52xx_suspend; | 27 | struct mpc52xx_suspend mpc52xx_suspend; |
| @@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t state) | |||
| 100 | u32 clk_enables; | 100 | u32 clk_enables; |
| 101 | u32 msr, hid0; | 101 | u32 msr, hid0; |
| 102 | u32 intr_main_mask; | 102 | u32 intr_main_mask; |
| 103 | void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500; | 103 | void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500; |
| 104 | unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; | 104 | unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; |
| 105 | char saved_0x500[mpc52xx_ds_cached_size]; | 105 | char saved_0x500[mpc52xx_ds_cached_size]; |
| 106 | 106 | ||
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index de7fce9cb6eb..89fde43895c5 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | choice | 1 | choice |
| 2 | prompt "Machine Type" | 2 | prompt "82xx Board Type" |
| 3 | depends on PPC_82xx | 3 | depends on PPC_82xx |
| 4 | default MPC82xx_ADS | 4 | default MPC82xx_ADS |
| 5 | 5 | ||
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index 47cb09f08052..da20832b27f1 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c | |||
| @@ -49,7 +49,7 @@ | |||
| 49 | #include <linux/fs_enet_pd.h> | 49 | #include <linux/fs_enet_pd.h> |
| 50 | 50 | ||
| 51 | #include <sysdev/fsl_soc.h> | 51 | #include <sysdev/fsl_soc.h> |
| 52 | #include <../sysdev/cpm2_pic.h> | 52 | #include <sysdev/cpm2_pic.h> |
| 53 | 53 | ||
| 54 | #include "pq2ads.h" | 54 | #include "pq2ads.h" |
| 55 | 55 | ||
| @@ -507,7 +507,8 @@ void m82xx_pci_init_irq(void) | |||
| 507 | return; | 507 | return; |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | static int m82xx_pci_exclude_device(u_char bus, u_char devfn) | 510 | static int m82xx_pci_exclude_device(struct pci_controller *hose, |
| 511 | u_char bus, u_char devfn) | ||
| 511 | { | 512 | { |
| 512 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 513 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
| 513 | return PCIBIOS_DEVICE_NOT_FOUND; | 514 | return PCIBIOS_DEVICE_NOT_FOUND; |
| @@ -515,7 +516,7 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn) | |||
| 515 | return PCIBIOS_SUCCESSFUL; | 516 | return PCIBIOS_SUCCESSFUL; |
| 516 | } | 517 | } |
| 517 | 518 | ||
| 518 | void __init add_bridge(struct device_node *np) | 519 | static void __init mpc82xx_add_bridge(struct device_node *np) |
| 519 | { | 520 | { |
| 520 | int len; | 521 | int len; |
| 521 | struct pci_controller *hose; | 522 | struct pci_controller *hose; |
| @@ -542,19 +543,13 @@ void __init add_bridge(struct device_node *np) | |||
| 542 | 543 | ||
| 543 | pci_assign_all_buses = 1; | 544 | pci_assign_all_buses = 1; |
| 544 | 545 | ||
| 545 | hose = pcibios_alloc_controller(); | 546 | hose = pcibios_alloc_controller(np); |
| 546 | 547 | ||
| 547 | if (!hose) | 548 | if (!hose) |
| 548 | return; | 549 | return; |
| 549 | 550 | ||
| 550 | hose->arch_data = np; | ||
| 551 | hose->set_cfg_type = 1; | ||
| 552 | |||
| 553 | hose->first_busno = bus_range ? bus_range[0] : 0; | 551 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 554 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 552 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 555 | hose->bus_offset = 0; | ||
| 556 | |||
| 557 | hose->set_cfg_type = 1; | ||
| 558 | 553 | ||
| 559 | setup_indirect_pci(hose, | 554 | setup_indirect_pci(hose, |
| 560 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), | 555 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), |
| @@ -584,7 +579,7 @@ static void __init mpc82xx_ads_setup_arch(void) | |||
| 584 | #ifdef CONFIG_PCI | 579 | #ifdef CONFIG_PCI |
| 585 | ppc_md.pci_exclude_device = m82xx_pci_exclude_device; | 580 | ppc_md.pci_exclude_device = m82xx_pci_exclude_device; |
| 586 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 581 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 587 | add_bridge(np); | 582 | mpc82xx_add_bridge(np); |
| 588 | 583 | ||
| 589 | of_node_put(np); | 584 | of_node_put(np); |
| 590 | #endif | 585 | #endif |
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 19cafdf6df93..ec305f18abd8 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | choice | 1 | choice |
| 2 | prompt "Machine Type" | 2 | prompt "83xx Board Type" |
| 3 | depends on PPC_83xx | 3 | depends on PPC_83xx |
| 4 | default MPC834x_MDS | 4 | default MPC834x_MDS |
| 5 | 5 | ||
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 31a91b53f528..5a98f885779f 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # | 1 | # |
| 2 | # Makefile for the PowerPC 83xx linux kernel. | 2 | # Makefile for the PowerPC 83xx linux kernel. |
| 3 | # | 3 | # |
| 4 | obj-y := misc.o | 4 | obj-y := misc.o usb.o |
| 5 | obj-$(CONFIG_PCI) += pci.o | 5 | obj-$(CONFIG_PCI) += pci.o |
| 6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o | 6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o |
| 7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o | 7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o |
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 96970ac887ee..3edfe170a03b 100644 --- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c | |||
| @@ -28,11 +28,6 @@ | |||
| 28 | #define DBG(fmt...) | 28 | #define DBG(fmt...) |
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #ifndef CONFIG_PCI | ||
| 32 | unsigned long isa_io_base = 0; | ||
| 33 | unsigned long isa_mem_base = 0; | ||
| 34 | #endif | ||
| 35 | |||
| 36 | /* ************************************************************************ | 31 | /* ************************************************************************ |
| 37 | * | 32 | * |
| 38 | * Setup the architecture | 33 | * Setup the architecture |
| @@ -49,10 +44,11 @@ static void __init mpc8313_rdb_setup_arch(void) | |||
| 49 | 44 | ||
| 50 | #ifdef CONFIG_PCI | 45 | #ifdef CONFIG_PCI |
| 51 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 46 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 52 | add_bridge(np); | 47 | mpc83xx_add_bridge(np); |
| 53 | 48 | ||
| 54 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 49 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 55 | #endif | 50 | #endif |
| 51 | mpc831x_usb_cfg(); | ||
| 56 | } | 52 | } |
| 57 | 53 | ||
| 58 | void __init mpc8313_rdb_init_IRQ(void) | 54 | void __init mpc8313_rdb_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 94843ed52a93..b39cb52c6fb9 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
| @@ -49,11 +49,6 @@ | |||
| 49 | #define DBG(fmt...) | 49 | #define DBG(fmt...) |
| 50 | #endif | 50 | #endif |
| 51 | 51 | ||
| 52 | #ifndef CONFIG_PCI | ||
| 53 | unsigned long isa_io_base = 0; | ||
| 54 | unsigned long isa_mem_base = 0; | ||
| 55 | #endif | ||
| 56 | |||
| 57 | static u8 *bcsr_regs = NULL; | 52 | static u8 *bcsr_regs = NULL; |
| 58 | 53 | ||
| 59 | /* ************************************************************************ | 54 | /* ************************************************************************ |
| @@ -80,7 +75,7 @@ static void __init mpc832x_sys_setup_arch(void) | |||
| 80 | 75 | ||
| 81 | #ifdef CONFIG_PCI | 76 | #ifdef CONFIG_PCI |
| 82 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 77 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 83 | add_bridge(np); | 78 | mpc83xx_add_bridge(np); |
| 84 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 79 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 85 | #endif | 80 | #endif |
| 86 | 81 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 3db68b73fc32..b2b28a44738c 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
| @@ -32,11 +32,6 @@ | |||
| 32 | #define DBG(fmt...) | 32 | #define DBG(fmt...) |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | #ifndef CONFIG_PCI | ||
| 36 | unsigned long isa_io_base = 0; | ||
| 37 | unsigned long isa_mem_base = 0; | ||
| 38 | #endif | ||
| 39 | |||
| 40 | /* ************************************************************************ | 35 | /* ************************************************************************ |
| 41 | * | 36 | * |
| 42 | * Setup the architecture | 37 | * Setup the architecture |
| @@ -53,7 +48,7 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
| 53 | 48 | ||
| 54 | #ifdef CONFIG_PCI | 49 | #ifdef CONFIG_PCI |
| 55 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 50 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 56 | add_bridge(np); | 51 | mpc83xx_add_bridge(np); |
| 57 | 52 | ||
| 58 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 53 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 59 | #endif | 54 | #endif |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 40a01947d684..47ba5446f63c 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c | |||
| @@ -38,11 +38,6 @@ | |||
| 38 | 38 | ||
| 39 | #include "mpc83xx.h" | 39 | #include "mpc83xx.h" |
| 40 | 40 | ||
| 41 | #ifndef CONFIG_PCI | ||
| 42 | unsigned long isa_io_base = 0; | ||
| 43 | unsigned long isa_mem_base = 0; | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* ************************************************************************ | 41 | /* ************************************************************************ |
| 47 | * | 42 | * |
| 48 | * Setup the architecture | 43 | * Setup the architecture |
| @@ -59,10 +54,12 @@ static void __init mpc834x_itx_setup_arch(void) | |||
| 59 | 54 | ||
| 60 | #ifdef CONFIG_PCI | 55 | #ifdef CONFIG_PCI |
| 61 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 56 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 62 | add_bridge(np); | 57 | mpc83xx_add_bridge(np); |
| 63 | 58 | ||
| 64 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 59 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 65 | #endif | 60 | #endif |
| 61 | |||
| 62 | mpc834x_usb_cfg(); | ||
| 66 | } | 63 | } |
| 67 | 64 | ||
| 68 | static void __init mpc834x_itx_init_IRQ(void) | 65 | static void __init mpc834x_itx_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 10394b2d7e7a..4c9ff9cadfe4 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c | |||
| @@ -38,61 +38,17 @@ | |||
| 38 | 38 | ||
| 39 | #include "mpc83xx.h" | 39 | #include "mpc83xx.h" |
| 40 | 40 | ||
| 41 | #ifndef CONFIG_PCI | ||
| 42 | unsigned long isa_io_base = 0; | ||
| 43 | unsigned long isa_mem_base = 0; | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #define BCSR5_INT_USB 0x02 | 41 | #define BCSR5_INT_USB 0x02 |
| 47 | /* Note: This is only for PB, not for PB+PIB | 42 | static int mpc834xemds_usb_cfg(void) |
| 48 | * On PB only port0 is connected using ULPI */ | ||
| 49 | static int mpc834x_usb_cfg(void) | ||
| 50 | { | 43 | { |
| 51 | unsigned long sccr, sicrl; | 44 | struct device_node *np; |
| 52 | void __iomem *immap; | ||
| 53 | void __iomem *bcsr_regs = NULL; | 45 | void __iomem *bcsr_regs = NULL; |
| 54 | u8 bcsr5; | 46 | u8 bcsr5; |
| 55 | struct device_node *np = NULL; | ||
| 56 | int port0_is_dr = 0; | ||
| 57 | |||
| 58 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL) | ||
| 59 | port0_is_dr = 1; | ||
| 60 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){ | ||
| 61 | if (port0_is_dr) { | ||
| 62 | printk(KERN_WARNING | ||
| 63 | "There is only one USB port on PB board! \n"); | ||
| 64 | return -1; | ||
| 65 | } else if (!port0_is_dr) | ||
| 66 | /* No usb port enabled */ | ||
| 67 | return -1; | ||
| 68 | } | ||
| 69 | |||
| 70 | immap = ioremap(get_immrbase(), 0x1000); | ||
| 71 | if (!immap) | ||
| 72 | return -1; | ||
| 73 | |||
| 74 | /* Configure clock */ | ||
| 75 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
| 76 | if (port0_is_dr) | ||
| 77 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
| 78 | else | ||
| 79 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
| 80 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
| 81 | |||
| 82 | /* Configure Pin */ | ||
| 83 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
| 84 | /* set port0 only */ | ||
| 85 | if (port0_is_dr) | ||
| 86 | sicrl |= MPC83XX_SICRL_USB0; | ||
| 87 | else | ||
| 88 | sicrl &= ~(MPC83XX_SICRL_USB0); | ||
| 89 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
| 90 | |||
| 91 | iounmap(immap); | ||
| 92 | 47 | ||
| 48 | mpc834x_usb_cfg(); | ||
| 93 | /* Map BCSR area */ | 49 | /* Map BCSR area */ |
| 94 | np = of_find_node_by_name(NULL, "bcsr"); | 50 | np = of_find_node_by_name(NULL, "bcsr"); |
| 95 | if (np != 0) { | 51 | if (np) { |
| 96 | struct resource res; | 52 | struct resource res; |
| 97 | 53 | ||
| 98 | of_address_to_resource(np, 0, &res); | 54 | of_address_to_resource(np, 0, &res); |
| @@ -129,12 +85,12 @@ static void __init mpc834x_mds_setup_arch(void) | |||
| 129 | 85 | ||
| 130 | #ifdef CONFIG_PCI | 86 | #ifdef CONFIG_PCI |
| 131 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 87 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 132 | add_bridge(np); | 88 | mpc83xx_add_bridge(np); |
| 133 | 89 | ||
| 134 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 135 | #endif | 91 | #endif |
| 136 | 92 | ||
| 137 | mpc834x_usb_cfg(); | 93 | mpc834xemds_usb_cfg(); |
| 138 | } | 94 | } |
| 139 | 95 | ||
| 140 | static void __init mpc834x_mds_init_IRQ(void) | 96 | static void __init mpc834x_mds_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index bceeff8bbfd2..0e615fd65c1f 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c | |||
| @@ -55,11 +55,6 @@ | |||
| 55 | #define DBG(fmt...) | 55 | #define DBG(fmt...) |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | #ifndef CONFIG_PCI | ||
| 59 | unsigned long isa_io_base = 0; | ||
| 60 | unsigned long isa_mem_base = 0; | ||
| 61 | #endif | ||
| 62 | |||
| 63 | static u8 *bcsr_regs = NULL; | 58 | static u8 *bcsr_regs = NULL; |
| 64 | 59 | ||
| 65 | /* ************************************************************************ | 60 | /* ************************************************************************ |
| @@ -86,7 +81,7 @@ static void __init mpc836x_mds_setup_arch(void) | |||
| 86 | 81 | ||
| 87 | #ifdef CONFIG_PCI | 82 | #ifdef CONFIG_PCI |
| 88 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 83 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 89 | add_bridge(np); | 84 | mpc83xx_add_bridge(np); |
| 90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 85 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
| 91 | #endif | 86 | #endif |
| 92 | 87 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 9cd03b59c8f4..589ee55730f3 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
| 5 | #include <linux/device.h> | 5 | #include <linux/device.h> |
| 6 | #include <asm/pci-bridge.h> | ||
| 6 | 7 | ||
| 7 | /* System Clock Control Register */ | 8 | /* System Clock Control Register */ |
| 8 | #define MPC83XX_SCCR_OFFS 0xA08 | 9 | #define MPC83XX_SCCR_OFFS 0xA08 |
| 10 | #define MPC83XX_SCCR_USB_MASK 0x00f00000 | ||
| 9 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 | 11 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 |
| 10 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 | 12 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 |
| 11 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 | 13 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 |
| @@ -15,21 +17,43 @@ | |||
| 15 | 17 | ||
| 16 | /* system i/o configuration register low */ | 18 | /* system i/o configuration register low */ |
| 17 | #define MPC83XX_SICRL_OFFS 0x114 | 19 | #define MPC83XX_SICRL_OFFS 0x114 |
| 18 | #define MPC83XX_SICRL_USB0 0x40000000 | 20 | #define MPC834X_SICRL_USB_MASK 0x60000000 |
| 19 | #define MPC83XX_SICRL_USB1 0x20000000 | 21 | #define MPC834X_SICRL_USB0 0x40000000 |
| 22 | #define MPC834X_SICRL_USB1 0x20000000 | ||
| 23 | #define MPC831X_SICRL_USB_MASK 0x00000c00 | ||
| 24 | #define MPC831X_SICRL_USB_ULPI 0x00000800 | ||
| 20 | 25 | ||
| 21 | /* system i/o configuration register high */ | 26 | /* system i/o configuration register high */ |
| 22 | #define MPC83XX_SICRH_OFFS 0x118 | 27 | #define MPC83XX_SICRH_OFFS 0x118 |
| 23 | #define MPC83XX_SICRH_USB_UTMI 0x00020000 | 28 | #define MPC834X_SICRH_USB_UTMI 0x00020000 |
| 29 | #define MPC831X_SICRH_USB_MASK 0x000000e0 | ||
| 30 | #define MPC831X_SICRH_USB_ULPI 0x000000a0 | ||
| 31 | |||
| 32 | /* USB Control Register */ | ||
| 33 | #define FSL_USB2_CONTROL_OFFS 0x500 | ||
| 34 | #define CONTROL_UTMI_PHY_EN 0x00000200 | ||
| 35 | #define CONTROL_REFSEL_48MHZ 0x00000080 | ||
| 36 | #define CONTROL_PHY_CLK_SEL_ULPI 0x00000400 | ||
| 37 | #define CONTROL_OTG_PORT 0x00000020 | ||
| 38 | |||
| 39 | /* USB PORTSC Registers */ | ||
| 40 | #define FSL_USB2_PORTSC1_OFFS 0x184 | ||
| 41 | #define FSL_USB2_PORTSC2_OFFS 0x188 | ||
| 42 | #define PORTSCX_PTW_16BIT 0x10000000 | ||
| 43 | #define PORTSCX_PTS_UTMI 0x00000000 | ||
| 44 | #define PORTSCX_PTS_ULPI 0x80000000 | ||
| 24 | 45 | ||
| 25 | /* | 46 | /* |
| 26 | * Declaration for the various functions exported by the | 47 | * Declaration for the various functions exported by the |
| 27 | * mpc83xx_* files. Mostly for use by mpc83xx_setup | 48 | * mpc83xx_* files. Mostly for use by mpc83xx_setup |
| 28 | */ | 49 | */ |
| 29 | 50 | ||
| 30 | extern int add_bridge(struct device_node *dev); | 51 | extern int mpc83xx_add_bridge(struct device_node *dev); |
| 31 | extern int mpc83xx_exclude_device(u_char bus, u_char devfn); | 52 | extern int mpc83xx_exclude_device(struct pci_controller *hose, |
| 53 | u_char bus, u_char devfn); | ||
| 32 | extern void mpc83xx_restart(char *cmd); | 54 | extern void mpc83xx_restart(char *cmd); |
| 33 | extern long mpc83xx_time_init(void); | 55 | extern long mpc83xx_time_init(void); |
| 56 | extern int mpc834x_usb_cfg(void); | ||
| 57 | extern int mpc831x_usb_cfg(void); | ||
| 34 | 58 | ||
| 35 | #endif /* __MPC83XX_H__ */ | 59 | #endif /* __MPC83XX_H__ */ |
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 774457d09e94..c0e2b89154e5 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
| @@ -33,19 +33,14 @@ | |||
| 33 | #define DBG(x...) | 33 | #define DBG(x...) |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | int mpc83xx_pci2_busno; | 36 | int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) |
| 37 | |||
| 38 | int mpc83xx_exclude_device(u_char bus, u_char devfn) | ||
| 39 | { | 37 | { |
| 40 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 38 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) |
| 41 | return PCIBIOS_DEVICE_NOT_FOUND; | 39 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 42 | if (mpc83xx_pci2_busno) | ||
| 43 | if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
| 44 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 45 | return PCIBIOS_SUCCESSFUL; | 40 | return PCIBIOS_SUCCESSFUL; |
| 46 | } | 41 | } |
| 47 | 42 | ||
| 48 | int __init add_bridge(struct device_node *dev) | 43 | int __init mpc83xx_add_bridge(struct device_node *dev) |
| 49 | { | 44 | { |
| 50 | int len; | 45 | int len; |
| 51 | struct pci_controller *hose; | 46 | struct pci_controller *hose; |
| @@ -66,11 +61,10 @@ int __init add_bridge(struct device_node *dev) | |||
| 66 | " bus 0\n", dev->full_name); | 61 | " bus 0\n", dev->full_name); |
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | hose = pcibios_alloc_controller(); | 64 | pci_assign_all_buses = 1; |
| 65 | hose = pcibios_alloc_controller(dev); | ||
| 70 | if (!hose) | 66 | if (!hose) |
| 71 | return -ENOMEM; | 67 | return -ENOMEM; |
| 72 | hose->arch_data = dev; | ||
| 73 | hose->set_cfg_type = 1; | ||
| 74 | 68 | ||
| 75 | hose->first_busno = bus_range ? bus_range[0] : 0; | 69 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 76 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 70 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| @@ -86,8 +80,6 @@ int __init add_bridge(struct device_node *dev) | |||
| 86 | if ((rsrc.start & 0xfffff) == 0x8600) { | 80 | if ((rsrc.start & 0xfffff) == 0x8600) { |
| 87 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); | 81 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); |
| 88 | primary = 0; | 82 | primary = 0; |
| 89 | hose->bus_offset = hose->first_busno; | ||
| 90 | mpc83xx_pci2_busno = hose->first_busno; | ||
| 91 | } | 83 | } |
| 92 | 84 | ||
| 93 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " | 85 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " |
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c new file mode 100644 index 000000000000..e7fdf013cd39 --- /dev/null +++ b/arch/powerpc/platforms/83xx/usb.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | /* | ||
| 2 | * Freescale 83xx USB SOC setup code | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Freescale Semiconductor, Inc. | ||
| 5 | * Author: Li Yang | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | |||
| 14 | #include <linux/stddef.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | |||
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/prom.h> | ||
| 20 | #include <sysdev/fsl_soc.h> | ||
| 21 | |||
| 22 | #include "mpc83xx.h" | ||
| 23 | |||
| 24 | |||
| 25 | #ifdef CONFIG_MPC834x | ||
| 26 | int mpc834x_usb_cfg(void) | ||
| 27 | { | ||
| 28 | unsigned long sccr, sicrl, sicrh; | ||
| 29 | void __iomem *immap; | ||
| 30 | struct device_node *np = NULL; | ||
| 31 | int port0_is_dr = 0, port1_is_dr = 0; | ||
| 32 | const void *prop, *dr_mode; | ||
| 33 | |||
| 34 | immap = ioremap(get_immrbase(), 0x1000); | ||
| 35 | if (!immap) | ||
| 36 | return -ENOMEM; | ||
| 37 | |||
| 38 | /* Read registers */ | ||
| 39 | /* Note: DR and MPH must use the same clock setting in SCCR */ | ||
| 40 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; | ||
| 41 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; | ||
| 42 | sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; | ||
| 43 | |||
| 44 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
| 45 | if (np) { | ||
| 46 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
| 47 | |||
| 48 | prop = of_get_property(np, "phy_type", NULL); | ||
| 49 | if (prop && (!strcmp(prop, "utmi") || | ||
| 50 | !strcmp(prop, "utmi_wide"))) { | ||
| 51 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
| 52 | sicrh |= MPC834X_SICRH_USB_UTMI; | ||
| 53 | port1_is_dr = 1; | ||
| 54 | } else if (prop && !strcmp(prop, "serial")) { | ||
| 55 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
| 56 | if (dr_mode && !strcmp(dr_mode, "otg")) { | ||
| 57 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
| 58 | port1_is_dr = 1; | ||
| 59 | } else { | ||
| 60 | sicrl |= MPC834X_SICRL_USB0; | ||
| 61 | } | ||
| 62 | } else if (prop && !strcmp(prop, "ulpi")) { | ||
| 63 | sicrl |= MPC834X_SICRL_USB0; | ||
| 64 | } else { | ||
| 65 | printk(KERN_WARNING "834x USB PHY type not supported\n"); | ||
| 66 | } | ||
| 67 | port0_is_dr = 1; | ||
| 68 | of_node_put(np); | ||
| 69 | } | ||
| 70 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph"); | ||
| 71 | if (np) { | ||
| 72 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
| 73 | |||
| 74 | prop = of_get_property(np, "port0", NULL); | ||
| 75 | if (prop) { | ||
| 76 | if (port0_is_dr) | ||
| 77 | printk(KERN_WARNING | ||
| 78 | "834x USB port0 can't be used by both DR and MPH!\n"); | ||
| 79 | sicrl |= MPC834X_SICRL_USB0; | ||
| 80 | } | ||
| 81 | prop = of_get_property(np, "port1", NULL); | ||
| 82 | if (prop) { | ||
| 83 | if (port1_is_dr) | ||
| 84 | printk(KERN_WARNING | ||
| 85 | "834x USB port1 can't be used by both DR and MPH!\n"); | ||
| 86 | sicrl |= MPC834X_SICRL_USB1; | ||
| 87 | } | ||
| 88 | of_node_put(np); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Write back */ | ||
| 92 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
| 93 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
| 94 | out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); | ||
| 95 | |||
| 96 | iounmap(immap); | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | #endif /* CONFIG_MPC834x */ | ||
| 100 | |||
| 101 | #ifdef CONFIG_PPC_MPC831x | ||
| 102 | int mpc831x_usb_cfg(void) | ||
| 103 | { | ||
| 104 | u32 temp; | ||
| 105 | void __iomem *immap, *usb_regs; | ||
| 106 | struct device_node *np = NULL; | ||
| 107 | const void *prop; | ||
| 108 | struct resource res; | ||
| 109 | int ret = 0; | ||
| 110 | #ifdef CONFIG_USB_OTG | ||
| 111 | const void *dr_mode; | ||
| 112 | #endif | ||
| 113 | |||
| 114 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
| 115 | if (!np) | ||
| 116 | return -ENODEV; | ||
| 117 | prop = of_get_property(np, "phy_type", NULL); | ||
| 118 | |||
| 119 | /* Map IMMR space for pin and clock settings */ | ||
| 120 | immap = ioremap(get_immrbase(), 0x1000); | ||
| 121 | if (!immap) { | ||
| 122 | of_node_put(np); | ||
| 123 | return -ENOMEM; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* Configure clock */ | ||
| 127 | temp = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
| 128 | temp &= ~MPC83XX_SCCR_USB_MASK; | ||
| 129 | temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
| 130 | out_be32(immap + MPC83XX_SCCR_OFFS, temp); | ||
| 131 | |||
| 132 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ | ||
| 133 | if (!strcmp(prop, "ulpi")) { | ||
| 134 | temp = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
| 135 | temp &= ~MPC831X_SICRL_USB_MASK; | ||
| 136 | temp |= MPC831X_SICRL_USB_ULPI; | ||
| 137 | out_be32(immap + MPC83XX_SICRL_OFFS, temp); | ||
| 138 | |||
| 139 | temp = in_be32(immap + MPC83XX_SICRH_OFFS); | ||
| 140 | temp &= ~MPC831X_SICRH_USB_MASK; | ||
| 141 | temp |= MPC831X_SICRH_USB_ULPI; | ||
| 142 | out_be32(immap + MPC83XX_SICRH_OFFS, temp); | ||
| 143 | } | ||
| 144 | |||
| 145 | iounmap(immap); | ||
| 146 | |||
| 147 | /* Map USB SOC space */ | ||
| 148 | ret = of_address_to_resource(np, 0, &res); | ||
| 149 | if (ret) { | ||
| 150 | of_node_put(np); | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | usb_regs = ioremap(res.start, res.end - res.start + 1); | ||
| 154 | |||
| 155 | /* Using on-chip PHY */ | ||
| 156 | if (!strcmp(prop, "utmi_wide") || | ||
| 157 | !strcmp(prop, "utmi")) { | ||
| 158 | /* Set UTMI_PHY_EN, REFSEL to 48MHZ */ | ||
| 159 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, | ||
| 160 | CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ); | ||
| 161 | /* Using external UPLI PHY */ | ||
| 162 | } else if (!strcmp(prop, "ulpi")) { | ||
| 163 | /* Set PHY_CLK_SEL to ULPI */ | ||
| 164 | temp = CONTROL_PHY_CLK_SEL_ULPI; | ||
| 165 | #ifdef CONFIG_USB_OTG | ||
| 166 | /* Set OTG_PORT */ | ||
| 167 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
| 168 | if (dr_mode && !strcmp(dr_mode, "otg")) | ||
| 169 | temp |= CONTROL_OTG_PORT; | ||
| 170 | #endif /* CONFIG_USB_OTG */ | ||
| 171 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); | ||
| 172 | } else { | ||
| 173 | printk(KERN_WARNING "831x USB PHY type not supported\n"); | ||
| 174 | ret = -EINVAL; | ||
| 175 | } | ||
| 176 | |||
| 177 | iounmap(usb_regs); | ||
| 178 | of_node_put(np); | ||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | #endif /* CONFIG_PPC_MPC831x */ | ||
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c index 3e62fcb04c1c..4fe376e9c3b6 100644 --- a/arch/powerpc/platforms/85xx/misc.c +++ b/arch/powerpc/platforms/85xx/misc.c | |||
| @@ -13,11 +13,43 @@ | |||
| 13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
| 16 | #include <asm/io.h> | ||
| 17 | #include <asm/prom.h> | ||
| 18 | #include <sysdev/fsl_soc.h> | ||
| 19 | |||
| 20 | static __be32 __iomem *rstcr; | ||
| 16 | 21 | ||
| 17 | extern void abort(void); | 22 | extern void abort(void); |
| 18 | 23 | ||
| 24 | static int __init mpc85xx_rstcr(void) | ||
| 25 | { | ||
| 26 | struct device_node *np; | ||
| 27 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
| 28 | if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { | ||
| 29 | const u32 *prop = of_get_property(np, "reg", NULL); | ||
| 30 | if (prop) { | ||
| 31 | /* map reset control register | ||
| 32 | * 0xE00B0 is offset of reset control register | ||
| 33 | */ | ||
| 34 | rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff); | ||
| 35 | if (!rstcr) | ||
| 36 | printk (KERN_EMERG "Error: reset control " | ||
| 37 | "register not mapped!\n"); | ||
| 38 | } | ||
| 39 | } else | ||
| 40 | printk (KERN_INFO "rstcr compatible register does not exist!\n"); | ||
| 41 | if (np) | ||
| 42 | of_node_put(np); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | arch_initcall(mpc85xx_rstcr); | ||
| 47 | |||
| 19 | void mpc85xx_restart(char *cmd) | 48 | void mpc85xx_restart(char *cmd) |
| 20 | { | 49 | { |
| 21 | local_irq_disable(); | 50 | local_irq_disable(); |
| 51 | if (rstcr) | ||
| 52 | /* set reset control register */ | ||
| 53 | out_be32(rstcr, 0x2); /* HRESET_REQ */ | ||
| 22 | abort(); | 54 | abort(); |
| 23 | } | 55 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c index bec84ffe708e..6fb90aab879f 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c | |||
| @@ -61,24 +61,11 @@ void __init mpc8544_ds_pic_init(void) | |||
| 61 | return; | 61 | return; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
| 65 | mpic = mpic_alloc(np, r.start, | 64 | mpic = mpic_alloc(np, r.start, |
| 66 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 65 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
| 67 | 16, 64, " OPENPIC "); | 66 | 0, 256, " OpenPIC "); |
| 68 | BUG_ON(mpic == NULL); | 67 | BUG_ON(mpic == NULL); |
| 69 | 68 | ||
| 70 | /* | ||
| 71 | * 48 Internal Interrupts | ||
| 72 | */ | ||
| 73 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
| 74 | mpic_assign_isu(mpic, 1, r.start + 0x10400); | ||
| 75 | mpic_assign_isu(mpic, 2, r.start + 0x10600); | ||
| 76 | |||
| 77 | /* | ||
| 78 | * 16 External interrupts | ||
| 79 | */ | ||
| 80 | mpic_assign_isu(mpic, 3, r.start + 0x10000); | ||
| 81 | |||
| 82 | mpic_init(mpic); | 69 | mpic_init(mpic); |
| 83 | 70 | ||
| 84 | #ifdef CONFIG_PPC_I8259 | 71 | #ifdef CONFIG_PPC_I8259 |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h index 83415db33378..7286ffac2c1d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx.h +++ b/arch/powerpc/platforms/85xx/mpc85xx.h | |||
| @@ -15,4 +15,4 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | extern void mpc85xx_restart(char *); | 17 | extern void mpc85xx_restart(char *); |
| 18 | extern int add_bridge(struct device_node *dev); | 18 | extern int mpc85xx_add_bridge(struct device_node *dev); |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 5d27621f0927..7235f702394c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
| @@ -38,13 +38,9 @@ | |||
| 38 | #include <asm/fs_pd.h> | 38 | #include <asm/fs_pd.h> |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | #ifndef CONFIG_PCI | ||
| 42 | unsigned long isa_io_base = 0; | ||
| 43 | unsigned long isa_mem_base = 0; | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #ifdef CONFIG_PCI | 41 | #ifdef CONFIG_PCI |
| 47 | static int mpc85xx_exclude_device(u_char bus, u_char devfn) | 42 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
| 43 | u_char bus, u_char devfn) | ||
| 48 | { | 44 | { |
| 49 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 45 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
| 50 | return PCIBIOS_DEVICE_NOT_FOUND; | 46 | return PCIBIOS_DEVICE_NOT_FOUND; |
| @@ -91,30 +87,10 @@ static void __init mpc85xx_ads_pic_init(void) | |||
| 91 | 87 | ||
| 92 | mpic = mpic_alloc(np, r.start, | 88 | mpic = mpic_alloc(np, r.start, |
| 93 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 89 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
| 94 | 4, 0, " OpenPIC "); | 90 | 0, 256, " OpenPIC "); |
| 95 | BUG_ON(mpic == NULL); | 91 | BUG_ON(mpic == NULL); |
| 96 | of_node_put(np); | 92 | of_node_put(np); |
| 97 | 93 | ||
| 98 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
| 99 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
| 100 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
| 101 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
| 102 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
| 103 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
| 104 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
| 105 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
| 106 | |||
| 107 | /* Unused on this platform (leave room for 8548) */ | ||
| 108 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
| 109 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
| 110 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
| 111 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
| 112 | |||
| 113 | /* External Interrupts */ | ||
| 114 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
| 115 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
| 116 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
| 117 | |||
| 118 | mpic_init(mpic); | 94 | mpic_init(mpic); |
| 119 | 95 | ||
| 120 | #ifdef CONFIG_CPM2 | 96 | #ifdef CONFIG_CPM2 |
| @@ -241,7 +217,7 @@ static void __init mpc85xx_ads_setup_arch(void) | |||
| 241 | 217 | ||
| 242 | #ifdef CONFIG_PCI | 218 | #ifdef CONFIG_PCI |
| 243 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 219 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 244 | add_bridge(np); | 220 | mpc85xx_add_bridge(np); |
| 245 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 221 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
| 246 | #endif | 222 | #endif |
| 247 | } | 223 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 1490eb3ce0d3..50c8d6458362 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c | |||
| @@ -47,11 +47,6 @@ | |||
| 47 | #include <sysdev/fsl_soc.h> | 47 | #include <sysdev/fsl_soc.h> |
| 48 | #include "mpc85xx.h" | 48 | #include "mpc85xx.h" |
| 49 | 49 | ||
| 50 | #ifndef CONFIG_PCI | ||
| 51 | unsigned long isa_io_base = 0; | ||
| 52 | unsigned long isa_mem_base = 0; | ||
| 53 | #endif | ||
| 54 | |||
| 55 | static int cds_pci_slot = 2; | 50 | static int cds_pci_slot = 2; |
| 56 | static volatile u8 *cadmus; | 51 | static volatile u8 *cadmus; |
| 57 | 52 | ||
| @@ -60,15 +55,11 @@ static volatile u8 *cadmus; | |||
| 60 | #define ARCADIA_HOST_BRIDGE_IDSEL 17 | 55 | #define ARCADIA_HOST_BRIDGE_IDSEL 17 |
| 61 | #define ARCADIA_2ND_BRIDGE_IDSEL 3 | 56 | #define ARCADIA_2ND_BRIDGE_IDSEL 3 |
| 62 | 57 | ||
| 63 | extern int mpc85xx_pci2_busno; | 58 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
| 64 | 59 | u_char bus, u_char devfn) | |
| 65 | static int mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
| 66 | { | 60 | { |
| 67 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 61 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) |
| 68 | return PCIBIOS_DEVICE_NOT_FOUND; | 62 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 69 | if (mpc85xx_pci2_busno) | ||
| 70 | if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
| 71 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 72 | /* We explicitly do not go past the Tundra 320 Bridge */ | 63 | /* We explicitly do not go past the Tundra 320 Bridge */ |
| 73 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) | 64 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) |
| 74 | return PCIBIOS_DEVICE_NOT_FOUND; | 65 | return PCIBIOS_DEVICE_NOT_FOUND; |
| @@ -78,52 +69,44 @@ static int mpc85xx_exclude_device(u_char bus, u_char devfn) | |||
| 78 | return PCIBIOS_SUCCESSFUL; | 69 | return PCIBIOS_SUCCESSFUL; |
| 79 | } | 70 | } |
| 80 | 71 | ||
| 81 | static void __init mpc85xx_cds_pcibios_fixup(void) | 72 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) |
| 82 | { | 73 | { |
| 83 | struct pci_dev *dev; | 74 | u_char c; |
| 84 | u_char c; | 75 | if (dev->vendor == PCI_VENDOR_ID_VIA) { |
| 85 | 76 | switch (dev->device) { | |
| 86 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | 77 | case PCI_DEVICE_ID_VIA_82C586_1: |
| 87 | PCI_DEVICE_ID_VIA_82C586_1, NULL))) { | 78 | /* |
| 79 | * U-Boot does not set the enable bits | ||
| 80 | * for the IDE device. Force them on here. | ||
| 81 | */ | ||
| 82 | pci_read_config_byte(dev, 0x40, &c); | ||
| 83 | c |= 0x03; /* IDE: Chip Enable Bits */ | ||
| 84 | pci_write_config_byte(dev, 0x40, c); | ||
| 85 | |||
| 86 | /* | ||
| 87 | * Since only primary interface works, force the | ||
| 88 | * IDE function to standard primary IDE interrupt | ||
| 89 | * w/ 8259 offset | ||
| 90 | */ | ||
| 91 | dev->irq = 14; | ||
| 92 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
| 93 | break; | ||
| 88 | /* | 94 | /* |
| 89 | * U-Boot does not set the enable bits | 95 | * Force legacy USB interrupt routing |
| 90 | * for the IDE device. Force them on here. | ||
| 91 | */ | 96 | */ |
| 92 | pci_read_config_byte(dev, 0x40, &c); | 97 | case PCI_DEVICE_ID_VIA_82C586_2: |
| 93 | c |= 0x03; /* IDE: Chip Enable Bits */ | 98 | /* There are two USB controllers. |
| 94 | pci_write_config_byte(dev, 0x40, c); | 99 | * Identify them by functon number |
| 95 | |||
| 96 | /* | ||
| 97 | * Since only primary interface works, force the | ||
| 98 | * IDE function to standard primary IDE interrupt | ||
| 99 | * w/ 8259 offset | ||
| 100 | */ | 100 | */ |
| 101 | dev->irq = 14; | 101 | if (PCI_FUNC(dev->devfn)) |
| 102 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | 102 | dev->irq = 11; |
| 103 | pci_dev_put(dev); | 103 | else |
| 104 | } | 104 | dev->irq = 10; |
| 105 | 105 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | |
| 106 | /* | 106 | default: |
| 107 | * Force legacy USB interrupt routing | 107 | break; |
| 108 | */ | 108 | } |
| 109 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
| 110 | PCI_DEVICE_ID_VIA_82C586_2, NULL))) { | ||
| 111 | dev->irq = 10; | ||
| 112 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); | ||
| 113 | pci_dev_put(dev); | ||
| 114 | } | ||
| 115 | |||
| 116 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
| 117 | PCI_DEVICE_ID_VIA_82C586_2, dev))) { | ||
| 118 | dev->irq = 11; | ||
| 119 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); | ||
| 120 | pci_dev_put(dev); | ||
| 121 | } | 109 | } |
| 122 | |||
| 123 | /* Now map all the PCI irqs */ | ||
| 124 | dev = NULL; | ||
| 125 | for_each_pci_dev(dev) | ||
| 126 | pci_read_irq_line(dev); | ||
| 127 | } | 110 | } |
| 128 | 111 | ||
| 129 | #ifdef CONFIG_PPC_I8259 | 112 | #ifdef CONFIG_PPC_I8259 |
| @@ -165,33 +148,12 @@ static void __init mpc85xx_cds_pic_init(void) | |||
| 165 | 148 | ||
| 166 | mpic = mpic_alloc(np, r.start, | 149 | mpic = mpic_alloc(np, r.start, |
| 167 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 150 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
| 168 | 4, 0, " OpenPIC "); | 151 | 0, 256, " OpenPIC "); |
| 169 | BUG_ON(mpic == NULL); | 152 | BUG_ON(mpic == NULL); |
| 170 | 153 | ||
| 171 | /* Return the mpic node */ | 154 | /* Return the mpic node */ |
| 172 | of_node_put(np); | 155 | of_node_put(np); |
| 173 | 156 | ||
| 174 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
| 175 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
| 176 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
| 177 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
| 178 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
| 179 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
| 180 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
| 181 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
| 182 | |||
| 183 | /* Used only for 8548 so far, but no harm in | ||
| 184 | * allocating them for everyone */ | ||
| 185 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
| 186 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
| 187 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
| 188 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
| 189 | |||
| 190 | /* External Interrupts */ | ||
| 191 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
| 192 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
| 193 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
| 194 | |||
| 195 | mpic_init(mpic); | 157 | mpic_init(mpic); |
| 196 | 158 | ||
| 197 | #ifdef CONFIG_PPC_I8259 | 159 | #ifdef CONFIG_PPC_I8259 |
| @@ -257,9 +219,9 @@ static void __init mpc85xx_cds_setup_arch(void) | |||
| 257 | 219 | ||
| 258 | #ifdef CONFIG_PCI | 220 | #ifdef CONFIG_PCI |
| 259 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 221 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 260 | add_bridge(np); | 222 | mpc85xx_add_bridge(np); |
| 261 | 223 | ||
| 262 | ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; | 224 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; |
| 263 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 225 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
| 264 | #endif | 226 | #endif |
| 265 | } | 227 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index e3dddbfe66ff..004b80bd0b84 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -59,11 +59,6 @@ | |||
| 59 | #define DBG(fmt...) | 59 | #define DBG(fmt...) |
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | #ifndef CONFIG_PCI | ||
| 63 | unsigned long isa_io_base = 0; | ||
| 64 | unsigned long isa_mem_base = 0; | ||
| 65 | #endif | ||
| 66 | |||
| 67 | /* ************************************************************************ | 62 | /* ************************************************************************ |
| 68 | * | 63 | * |
| 69 | * Setup the architecture | 64 | * Setup the architecture |
| @@ -100,7 +95,7 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
| 100 | 95 | ||
| 101 | #ifdef CONFIG_PCI | 96 | #ifdef CONFIG_PCI |
| 102 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 97 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { |
| 103 | add_bridge(np); | 98 | mpc85xx_add_bridge(np); |
| 104 | } | 99 | } |
| 105 | of_node_put(np); | 100 | of_node_put(np); |
| 106 | #endif | 101 | #endif |
| @@ -181,29 +176,10 @@ static void __init mpc85xx_mds_pic_init(void) | |||
| 181 | 176 | ||
| 182 | mpic = mpic_alloc(np, r.start, | 177 | mpic = mpic_alloc(np, r.start, |
| 183 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 178 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
| 184 | 4, 0, " OpenPIC "); | 179 | 0, 256, " OpenPIC "); |
| 185 | BUG_ON(mpic == NULL); | 180 | BUG_ON(mpic == NULL); |
| 186 | of_node_put(np); | 181 | of_node_put(np); |
| 187 | 182 | ||
| 188 | /* Internal Interrupts */ | ||
| 189 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
| 190 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
| 191 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
| 192 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
| 193 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
| 194 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
| 195 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
| 196 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
| 197 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
| 198 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
| 199 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
| 200 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
| 201 | |||
| 202 | /* External Interrupts */ | ||
| 203 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
| 204 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
| 205 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
| 206 | |||
| 207 | mpic_init(mpic); | 183 | mpic_init(mpic); |
| 208 | 184 | ||
| 209 | #ifdef CONFIG_QUICC_ENGINE | 185 | #ifdef CONFIG_QUICC_ENGINE |
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c index 48f17e23d771..8118417b7364 100644 --- a/arch/powerpc/platforms/85xx/pci.c +++ b/arch/powerpc/platforms/85xx/pci.c | |||
| @@ -33,10 +33,8 @@ | |||
| 33 | #define DBG(x...) | 33 | #define DBG(x...) |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | int mpc85xx_pci2_busno = 0; | ||
| 37 | |||
| 38 | #ifdef CONFIG_PCI | 36 | #ifdef CONFIG_PCI |
| 39 | int __init add_bridge(struct device_node *dev) | 37 | int __init mpc85xx_add_bridge(struct device_node *dev) |
| 40 | { | 38 | { |
| 41 | int len; | 39 | int len; |
| 42 | struct pci_controller *hose; | 40 | struct pci_controller *hose; |
| @@ -57,11 +55,10 @@ int __init add_bridge(struct device_node *dev) | |||
| 57 | " bus 0\n", dev->full_name); | 55 | " bus 0\n", dev->full_name); |
| 58 | } | 56 | } |
| 59 | 57 | ||
| 60 | hose = pcibios_alloc_controller(); | 58 | pci_assign_all_buses = 1; |
| 59 | hose = pcibios_alloc_controller(dev); | ||
| 61 | if (!hose) | 60 | if (!hose) |
| 62 | return -ENOMEM; | 61 | return -ENOMEM; |
| 63 | hose->arch_data = dev; | ||
| 64 | hose->set_cfg_type = 1; | ||
| 65 | 62 | ||
| 66 | hose->first_busno = bus_range ? bus_range[0] : 0; | 63 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 67 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 64 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| @@ -74,8 +71,6 @@ int __init add_bridge(struct device_node *dev) | |||
| 74 | if ((rsrc.start & 0xfffff) == 0x9000) { | 71 | if ((rsrc.start & 0xfffff) == 0x9000) { |
| 75 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); | 72 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); |
| 76 | primary = 0; | 73 | primary = 0; |
| 77 | hose->bus_offset = hose->first_busno; | ||
| 78 | mpc85xx_pci2_busno = hose->first_busno; | ||
| 79 | } | 74 | } |
| 80 | 75 | ||
| 81 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " | 76 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index d1bcff500464..0faebfdc1596 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | choice | 1 | choice |
| 2 | prompt "Machine Type" | 2 | prompt "86xx Board Type" |
| 3 | depends on PPC_86xx | 3 | depends on PPC_86xx |
| 4 | default MPC8641_HPCN | 4 | default MPC8641_HPCN |
| 5 | 5 | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h index 2834462590b8..23f7ed2a7f88 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx.h +++ b/arch/powerpc/platforms/86xx/mpc86xx.h | |||
| @@ -15,15 +15,10 @@ | |||
| 15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). | 15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | extern int add_bridge(struct device_node *dev); | 18 | extern int mpc86xx_add_bridge(struct device_node *dev); |
| 19 | 19 | ||
| 20 | extern int mpc86xx_exclude_device(u_char bus, u_char devfn); | 20 | extern int mpc86xx_exclude_device(struct pci_controller *hose, |
| 21 | 21 | u_char bus, u_char devfn); | |
| 22 | extern void setup_indirect_pcie(struct pci_controller *hose, | ||
| 23 | u32 cfg_addr, u32 cfg_data); | ||
| 24 | extern void setup_indirect_pcie_nomap(struct pci_controller *hose, | ||
| 25 | void __iomem *cfg_addr, | ||
| 26 | void __iomem *cfg_data); | ||
| 27 | 22 | ||
| 28 | extern void __init mpc86xx_smp_init(void); | 23 | extern void __init mpc86xx_smp_init(void); |
| 29 | 24 | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 1051702c8d4f..5b01ec7c13dc 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
| @@ -44,13 +44,6 @@ | |||
| 44 | #define DBG(fmt...) do { } while(0) | 44 | #define DBG(fmt...) do { } while(0) |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | #ifndef CONFIG_PCI | ||
| 48 | unsigned long isa_io_base = 0; | ||
| 49 | unsigned long isa_mem_base = 0; | ||
| 50 | unsigned long pci_dram_offset = 0; | ||
| 51 | #endif | ||
| 52 | |||
| 53 | |||
| 54 | #ifdef CONFIG_PCI | 47 | #ifdef CONFIG_PCI |
| 55 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) | 48 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) |
| 56 | { | 49 | { |
| @@ -81,22 +74,9 @@ mpc86xx_hpcn_init_irq(void) | |||
| 81 | /* Alloc mpic structure and per isu has 16 INT entries. */ | 74 | /* Alloc mpic structure and per isu has 16 INT entries. */ |
| 82 | mpic1 = mpic_alloc(np, res.start, | 75 | mpic1 = mpic_alloc(np, res.start, |
| 83 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 76 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
| 84 | 16, NR_IRQS - 4, | 77 | 0, 256, " MPIC "); |
| 85 | " MPIC "); | ||
| 86 | BUG_ON(mpic1 == NULL); | 78 | BUG_ON(mpic1 == NULL); |
| 87 | 79 | ||
| 88 | mpic_assign_isu(mpic1, 0, res.start + 0x10000); | ||
| 89 | |||
| 90 | /* 48 Internal Interrupts */ | ||
| 91 | mpic_assign_isu(mpic1, 1, res.start + 0x10200); | ||
| 92 | mpic_assign_isu(mpic1, 2, res.start + 0x10400); | ||
| 93 | mpic_assign_isu(mpic1, 3, res.start + 0x10600); | ||
| 94 | |||
| 95 | /* 16 External interrupts | ||
| 96 | * Moving them from [0 - 15] to [64 - 79] | ||
| 97 | */ | ||
| 98 | mpic_assign_isu(mpic1, 4, res.start + 0x10000); | ||
| 99 | |||
| 100 | mpic_init(mpic1); | 80 | mpic_init(mpic1); |
| 101 | 81 | ||
| 102 | #ifdef CONFIG_PCI | 82 | #ifdef CONFIG_PCI |
| @@ -319,6 +299,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev) | |||
| 319 | { | 299 | { |
| 320 | unsigned short temp; | 300 | unsigned short temp; |
| 321 | pci_write_config_word(dev, 0x04, 0x0405); | 301 | pci_write_config_word(dev, 0x04, 0x0405); |
| 302 | dev->class &= ~0x5; | ||
| 322 | pci_read_config_word(dev, 0x4a, &temp); | 303 | pci_read_config_word(dev, 0x4a, &temp); |
| 323 | temp |= 0x1000; | 304 | temp |= 0x1000; |
| 324 | pci_write_config_word(dev, 0x4a, temp); | 305 | pci_write_config_word(dev, 0x4a, temp); |
| @@ -364,9 +345,7 @@ mpc86xx_hpcn_setup_arch(void) | |||
| 364 | 345 | ||
| 365 | #ifdef CONFIG_PCI | 346 | #ifdef CONFIG_PCI |
| 366 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 347 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 367 | add_bridge(np); | 348 | mpc86xx_add_bridge(np); |
| 368 | |||
| 369 | ppc_md.pci_exclude_device = mpc86xx_exclude_device; | ||
| 370 | #endif | 349 | #endif |
| 371 | 350 | ||
| 372 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); | 351 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); |
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 8235c562661f..73cd5b05a84e 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c | |||
| @@ -122,7 +122,6 @@ static void __init | |||
| 122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | 122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) |
| 123 | { | 123 | { |
| 124 | u16 cmd; | 124 | u16 cmd; |
| 125 | unsigned int temps; | ||
| 126 | 125 | ||
| 127 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", | 126 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", |
| 128 | pcie_offset, pcie_size); | 127 | pcie_offset, pcie_size); |
| @@ -133,22 +132,49 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | |||
| 133 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); | 132 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); |
| 134 | 133 | ||
| 135 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); | 134 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); |
| 136 | |||
| 137 | /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ | ||
| 138 | early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); | ||
| 139 | temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); | ||
| 140 | early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); | ||
| 141 | } | 135 | } |
| 142 | 136 | ||
| 143 | int mpc86xx_exclude_device(u_char bus, u_char devfn) | 137 | static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev) |
| 144 | { | 138 | { |
| 145 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 139 | struct resource *res; |
| 146 | return PCIBIOS_DEVICE_NOT_FOUND; | 140 | int i, res_idx = PCI_BRIDGE_RESOURCES; |
| 141 | struct pci_controller *hose; | ||
| 147 | 142 | ||
| 148 | return PCIBIOS_SUCCESSFUL; | 143 | /* |
| 144 | * Make the bridge be transparent. | ||
| 145 | */ | ||
| 146 | dev->transparent = 1; | ||
| 147 | |||
| 148 | hose = pci_bus_to_host(dev->bus); | ||
| 149 | if (!hose) { | ||
| 150 | printk(KERN_ERR "Can't find hose for bus %d\n", | ||
| 151 | dev->bus->number); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 155 | if (hose->io_resource.flags) { | ||
| 156 | res = &dev->resource[res_idx++]; | ||
| 157 | res->start = hose->io_resource.start; | ||
| 158 | res->end = hose->io_resource.end; | ||
| 159 | res->flags = hose->io_resource.flags; | ||
| 160 | } | ||
| 161 | |||
| 162 | for (i = 0; i < 3; i++) { | ||
| 163 | res = &dev->resource[res_idx + i]; | ||
| 164 | res->start = hose->mem_resources[i].start; | ||
| 165 | res->end = hose->mem_resources[i].end; | ||
| 166 | res->flags = hose->mem_resources[i].flags; | ||
| 167 | } | ||
| 149 | } | 168 | } |
| 150 | 169 | ||
| 151 | int __init add_bridge(struct device_node *dev) | 170 | |
| 171 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent); | ||
| 172 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent); | ||
| 173 | |||
| 174 | #define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */ | ||
| 175 | #define PCIE_LTSSM_L0 0x16 /* L0 state */ | ||
| 176 | |||
| 177 | int __init mpc86xx_add_bridge(struct device_node *dev) | ||
| 152 | { | 178 | { |
| 153 | int len; | 179 | int len; |
| 154 | struct pci_controller *hose; | 180 | struct pci_controller *hose; |
| @@ -156,6 +182,7 @@ int __init add_bridge(struct device_node *dev) | |||
| 156 | const int *bus_range; | 182 | const int *bus_range; |
| 157 | int has_address = 0; | 183 | int has_address = 0; |
| 158 | int primary = 0; | 184 | int primary = 0; |
| 185 | u16 val; | ||
| 159 | 186 | ||
| 160 | DBG("Adding PCIE host bridge %s\n", dev->full_name); | 187 | DBG("Adding PCIE host bridge %s\n", dev->full_name); |
| 161 | 188 | ||
| @@ -168,17 +195,23 @@ int __init add_bridge(struct device_node *dev) | |||
| 168 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 195 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
| 169 | " bus 0\n", dev->full_name); | 196 | " bus 0\n", dev->full_name); |
| 170 | 197 | ||
| 171 | hose = pcibios_alloc_controller(); | 198 | pci_assign_all_buses = 1; |
| 199 | hose = pcibios_alloc_controller(dev); | ||
| 172 | if (!hose) | 200 | if (!hose) |
| 173 | return -ENOMEM; | 201 | return -ENOMEM; |
| 174 | hose->arch_data = dev; | ||
| 175 | hose->set_cfg_type = 1; | ||
| 176 | 202 | ||
| 177 | /* last_busno = 0xfe cause by MPC8641 PCIE bug */ | 203 | hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG | |
| 204 | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; | ||
| 205 | |||
| 178 | hose->first_busno = bus_range ? bus_range[0] : 0x0; | 206 | hose->first_busno = bus_range ? bus_range[0] : 0x0; |
| 179 | hose->last_busno = bus_range ? bus_range[1] : 0xfe; | 207 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 208 | |||
| 209 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4); | ||
| 180 | 210 | ||
| 181 | setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); | 211 | /* Probe the hose link training status */ |
| 212 | early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val); | ||
| 213 | if (val < PCIE_LTSSM_L0) | ||
| 214 | return -ENXIO; | ||
| 182 | 215 | ||
| 183 | /* Setup the PCIE host controller. */ | 216 | /* Setup the PCIE host controller. */ |
| 184 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); | 217 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); |
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 0901dbada350..f1693550c70c 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/root_dev.h> | 32 | #include <linux/root_dev.h> |
| 33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
| 34 | #include <linux/rtc.h> | 34 | #include <linux/rtc.h> |
| 35 | #include <linux/fsl_devices.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/mmu.h> | 37 | #include <asm/mmu.h> |
| 37 | #include <asm/reg.h> | 38 | #include <asm/reg.h> |
| @@ -49,6 +50,10 @@ | |||
| 49 | 50 | ||
| 50 | #include "sysdev/mpc8xx_pic.h" | 51 | #include "sysdev/mpc8xx_pic.h" |
| 51 | 52 | ||
| 53 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 54 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
| 55 | #endif | ||
| 56 | |||
| 52 | void m8xx_calibrate_decr(void); | 57 | void m8xx_calibrate_decr(void); |
| 53 | extern void m8xx_wdt_handler_install(bd_t *bp); | 58 | extern void m8xx_wdt_handler_install(bd_t *bp); |
| 54 | extern int cpm_pic_init(void); | 59 | extern int cpm_pic_init(void); |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c36e475d93dc..dc27dab48df0 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #include <linux/fs_enet_pd.h> | 23 | #include <linux/fs_enet_pd.h> |
| 24 | #include <linux/fs_uart_pd.h> | 24 | #include <linux/fs_uart_pd.h> |
| 25 | #include <linux/fsl_devices.h> | ||
| 25 | #include <linux/mii.h> | 26 | #include <linux/mii.h> |
| 26 | 27 | ||
| 27 | #include <asm/delay.h> | 28 | #include <asm/delay.h> |
| @@ -51,6 +52,70 @@ static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); | |||
| 51 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); | 52 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); |
| 52 | static void init_scc3_ioports(struct fs_platform_info* ptr); | 53 | static void init_scc3_ioports(struct fs_platform_info* ptr); |
| 53 | 54 | ||
| 55 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 56 | static void pcmcia_hw_setup(int slot, int enable) | ||
| 57 | { | ||
| 58 | unsigned *bcsr_io; | ||
| 59 | |||
| 60 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
| 61 | if (enable) | ||
| 62 | clrbits32(bcsr_io, BCSR1_PCCEN); | ||
| 63 | else | ||
| 64 | setbits32(bcsr_io, BCSR1_PCCEN); | ||
| 65 | |||
| 66 | iounmap(bcsr_io); | ||
| 67 | } | ||
| 68 | |||
| 69 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) | ||
| 70 | { | ||
| 71 | u32 reg = 0; | ||
| 72 | unsigned *bcsr_io; | ||
| 73 | |||
| 74 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
| 75 | |||
| 76 | switch(vcc) { | ||
| 77 | case 0: | ||
| 78 | break; | ||
| 79 | case 33: | ||
| 80 | reg |= BCSR1_PCCVCC0; | ||
| 81 | break; | ||
| 82 | case 50: | ||
| 83 | reg |= BCSR1_PCCVCC1; | ||
| 84 | break; | ||
| 85 | default: | ||
| 86 | return 1; | ||
| 87 | } | ||
| 88 | |||
| 89 | switch(vpp) { | ||
| 90 | case 0: | ||
| 91 | break; | ||
| 92 | case 33: | ||
| 93 | case 50: | ||
| 94 | if(vcc == vpp) | ||
| 95 | reg |= BCSR1_PCCVPP1; | ||
| 96 | else | ||
| 97 | return 1; | ||
| 98 | break; | ||
| 99 | case 120: | ||
| 100 | if ((vcc == 33) || (vcc == 50)) | ||
| 101 | reg |= BCSR1_PCCVPP0; | ||
| 102 | else | ||
| 103 | return 1; | ||
| 104 | default: | ||
| 105 | return 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | /* first, turn off all power */ | ||
| 109 | clrbits32(bcsr_io, 0x00610000); | ||
| 110 | |||
| 111 | /* enable new powersettings */ | ||
| 112 | setbits32(bcsr_io, reg); | ||
| 113 | |||
| 114 | iounmap(bcsr_io); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | #endif | ||
| 118 | |||
| 54 | void __init mpc885ads_board_setup(void) | 119 | void __init mpc885ads_board_setup(void) |
| 55 | { | 120 | { |
| 56 | cpm8xx_t *cp; | 121 | cpm8xx_t *cp; |
| @@ -115,6 +180,12 @@ void __init mpc885ads_board_setup(void) | |||
| 115 | immr_unmap(io_port); | 180 | immr_unmap(io_port); |
| 116 | 181 | ||
| 117 | #endif | 182 | #endif |
| 183 | |||
| 184 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 185 | /*Set up board specific hook-ups*/ | ||
| 186 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; | ||
| 187 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; | ||
| 188 | #endif | ||
| 118 | } | 189 | } |
| 119 | 190 | ||
| 120 | 191 | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 361acfa2894c..33545d352e92 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -2,7 +2,7 @@ menu "Platform support" | |||
| 2 | 2 | ||
| 3 | choice | 3 | choice |
| 4 | prompt "Machine type" | 4 | prompt "Machine type" |
| 5 | depends on PPC64 || CLASSIC32 | 5 | depends on PPC64 || 6xx |
| 6 | default PPC_MULTIPLATFORM | 6 | default PPC_MULTIPLATFORM |
| 7 | 7 | ||
| 8 | config PPC_MULTIPLATFORM | 8 | config PPC_MULTIPLATFORM |
| @@ -16,15 +16,30 @@ config EMBEDDED6xx | |||
| 16 | bool "Embedded 6xx/7xx/7xxx-based board" | 16 | bool "Embedded 6xx/7xx/7xxx-based board" |
| 17 | depends on PPC32 && (BROKEN||BROKEN_ON_SMP) | 17 | depends on PPC32 && (BROKEN||BROKEN_ON_SMP) |
| 18 | 18 | ||
| 19 | config APUS | 19 | config PPC_82xx |
| 20 | bool "Amiga-APUS" | 20 | bool "Freescale 82xx" |
| 21 | depends on PPC32 && BROKEN | 21 | depends on 6xx |
| 22 | |||
| 23 | config PPC_83xx | ||
| 24 | bool "Freescale 83xx" | ||
| 25 | depends on 6xx | ||
| 26 | select FSL_SOC | ||
| 27 | select 83xx | ||
| 28 | select WANT_DEVICE_TREE | ||
| 29 | |||
| 30 | config PPC_86xx | ||
| 31 | bool "Freescale 86xx" | ||
| 32 | depends on 6xx | ||
| 33 | select FSL_SOC | ||
| 34 | select ALTIVEC | ||
| 22 | help | 35 | help |
| 23 | Select APUS if configuring for a PowerUP Amiga. | 36 | The Freescale E600 SoCs have 74xx cores. |
| 24 | More information is available at: | ||
| 25 | <http://linux-apus.sourceforge.net/>. | ||
| 26 | endchoice | 37 | endchoice |
| 27 | 38 | ||
| 39 | config CLASSIC32 | ||
| 40 | def_bool y | ||
| 41 | depends on 6xx && PPC_MULTIPLATFORM | ||
| 42 | |||
| 28 | source "arch/powerpc/platforms/pseries/Kconfig" | 43 | source "arch/powerpc/platforms/pseries/Kconfig" |
| 29 | source "arch/powerpc/platforms/iseries/Kconfig" | 44 | source "arch/powerpc/platforms/iseries/Kconfig" |
| 30 | source "arch/powerpc/platforms/chrp/Kconfig" | 45 | source "arch/powerpc/platforms/chrp/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype new file mode 100644 index 000000000000..b8b5fde94668 --- /dev/null +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -0,0 +1,221 @@ | |||
| 1 | config PPC64 | ||
| 2 | bool "64-bit kernel" | ||
| 3 | default n | ||
| 4 | help | ||
| 5 | This option selects whether a 32-bit or a 64-bit kernel | ||
| 6 | will be built. | ||
| 7 | |||
| 8 | menu "Processor support" | ||
| 9 | choice | ||
| 10 | prompt "Processor Type" | ||
| 11 | depends on PPC32 | ||
| 12 | default 6xx | ||
| 13 | help | ||
| 14 | There are five families of 32 bit PowerPC chips supported. | ||
| 15 | The most common ones are the desktop and server CPUs (601, 603, | ||
| 16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their | ||
| 17 | embedded 52xx/82xx/83xx/86xx counterparts. | ||
| 18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 | ||
| 19 | (85xx) each form a family of their own that is not compatible | ||
| 20 | with the others. | ||
| 21 | |||
| 22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. | ||
| 23 | |||
| 24 | config 6xx | ||
| 25 | bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" | ||
| 26 | select PPC_FPU | ||
| 27 | |||
| 28 | config PPC_85xx | ||
| 29 | bool "Freescale 85xx" | ||
| 30 | select E500 | ||
| 31 | select FSL_SOC | ||
| 32 | select 85xx | ||
| 33 | select WANT_DEVICE_TREE | ||
| 34 | |||
| 35 | config PPC_8xx | ||
| 36 | bool "Freescale 8xx" | ||
| 37 | select FSL_SOC | ||
| 38 | select 8xx | ||
| 39 | |||
| 40 | config 40x | ||
| 41 | bool "AMCC 40x" | ||
| 42 | select PPC_DCR_NATIVE | ||
| 43 | |||
| 44 | config 44x | ||
| 45 | bool "AMCC 44x" | ||
| 46 | select PPC_DCR_NATIVE | ||
| 47 | select WANT_DEVICE_TREE | ||
| 48 | |||
| 49 | config E200 | ||
| 50 | bool "Freescale e200" | ||
| 51 | |||
| 52 | endchoice | ||
| 53 | |||
| 54 | config POWER4_ONLY | ||
| 55 | bool "Optimize for POWER4" | ||
| 56 | depends on PPC64 | ||
| 57 | default n | ||
| 58 | ---help--- | ||
| 59 | Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. | ||
| 60 | The resulting binary will not work on POWER3 or RS64 processors | ||
| 61 | when compiled with binutils 2.15 or later. | ||
| 62 | |||
| 63 | config POWER3 | ||
| 64 | bool | ||
| 65 | depends on PPC64 | ||
| 66 | default y if !POWER4_ONLY | ||
| 67 | |||
| 68 | config POWER4 | ||
| 69 | depends on PPC64 | ||
| 70 | def_bool y | ||
| 71 | |||
| 72 | config 6xx | ||
| 73 | bool | ||
| 74 | |||
| 75 | # this is temp to handle compat with arch=ppc | ||
| 76 | config 8xx | ||
| 77 | bool | ||
| 78 | |||
| 79 | # this is temp to handle compat with arch=ppc | ||
| 80 | config 83xx | ||
| 81 | bool | ||
| 82 | |||
| 83 | # this is temp to handle compat with arch=ppc | ||
| 84 | config 85xx | ||
| 85 | bool | ||
| 86 | |||
| 87 | config E500 | ||
| 88 | bool | ||
| 89 | |||
| 90 | config PPC_FPU | ||
| 91 | bool | ||
| 92 | default y if PPC64 | ||
| 93 | |||
| 94 | config 4xx | ||
| 95 | bool | ||
| 96 | depends on 40x || 44x | ||
| 97 | default y | ||
| 98 | |||
| 99 | config BOOKE | ||
| 100 | bool | ||
| 101 | depends on E200 || E500 || 44x | ||
| 102 | default y | ||
| 103 | |||
| 104 | config FSL_BOOKE | ||
| 105 | bool | ||
| 106 | depends on E200 || E500 | ||
| 107 | default y | ||
| 108 | |||
| 109 | config PTE_64BIT | ||
| 110 | bool | ||
| 111 | depends on 44x || E500 | ||
| 112 | default y if 44x | ||
| 113 | default y if E500 && PHYS_64BIT | ||
| 114 | |||
| 115 | config PHYS_64BIT | ||
| 116 | bool 'Large physical address support' if E500 | ||
| 117 | depends on 44x || E500 | ||
| 118 | select RESOURCES_64BIT | ||
| 119 | default y if 44x | ||
| 120 | ---help--- | ||
| 121 | This option enables kernel support for larger than 32-bit physical | ||
| 122 | addresses. This features is not be available on all e500 cores. | ||
| 123 | |||
| 124 | If in doubt, say N here. | ||
| 125 | |||
| 126 | config ALTIVEC | ||
| 127 | bool "AltiVec Support" | ||
| 128 | depends on CLASSIC32 || POWER4 | ||
| 129 | ---help--- | ||
| 130 | This option enables kernel support for the Altivec extensions to the | ||
| 131 | PowerPC processor. The kernel currently supports saving and restoring | ||
| 132 | altivec registers, and turning on the 'altivec enable' bit so user | ||
| 133 | processes can execute altivec instructions. | ||
| 134 | |||
| 135 | This option is only usefully if you have a processor that supports | ||
| 136 | altivec (G4, otherwise known as 74xx series), but does not have | ||
| 137 | any affect on a non-altivec cpu (it does, however add code to the | ||
| 138 | kernel). | ||
| 139 | |||
| 140 | If in doubt, say Y here. | ||
| 141 | |||
| 142 | config SPE | ||
| 143 | bool "SPE Support" | ||
| 144 | depends on E200 || E500 | ||
| 145 | default y | ||
| 146 | ---help--- | ||
| 147 | This option enables kernel support for the Signal Processing | ||
| 148 | Extensions (SPE) to the PowerPC processor. The kernel currently | ||
| 149 | supports saving and restoring SPE registers, and turning on the | ||
| 150 | 'spe enable' bit so user processes can execute SPE instructions. | ||
| 151 | |||
| 152 | This option is only useful if you have a processor that supports | ||
| 153 | SPE (e500, otherwise known as 85xx series), but does not have any | ||
| 154 | effect on a non-spe cpu (it does, however add code to the kernel). | ||
| 155 | |||
| 156 | If in doubt, say Y here. | ||
| 157 | |||
| 158 | config PPC_STD_MMU | ||
| 159 | bool | ||
| 160 | depends on 6xx || POWER3 || POWER4 || PPC64 | ||
| 161 | default y | ||
| 162 | |||
| 163 | config PPC_STD_MMU_32 | ||
| 164 | def_bool y | ||
| 165 | depends on PPC_STD_MMU && PPC32 | ||
| 166 | |||
| 167 | config PPC_MM_SLICES | ||
| 168 | bool | ||
| 169 | default y if HUGETLB_PAGE | ||
| 170 | default n | ||
| 171 | |||
| 172 | config VIRT_CPU_ACCOUNTING | ||
| 173 | bool "Deterministic task and CPU time accounting" | ||
| 174 | depends on PPC64 | ||
| 175 | default y | ||
| 176 | help | ||
| 177 | Select this option to enable more accurate task and CPU time | ||
| 178 | accounting. This is done by reading a CPU counter on each | ||
| 179 | kernel entry and exit and on transitions within the kernel | ||
| 180 | between system, softirq and hardirq state, so there is a | ||
| 181 | small performance impact. This also enables accounting of | ||
| 182 | stolen time on logically-partitioned systems running on | ||
| 183 | IBM POWER5-based machines. | ||
| 184 | |||
| 185 | If in doubt, say Y here. | ||
| 186 | |||
| 187 | config SMP | ||
| 188 | depends on PPC_STD_MMU | ||
| 189 | bool "Symmetric multi-processing support" | ||
| 190 | ---help--- | ||
| 191 | This enables support for systems with more than one CPU. If you have | ||
| 192 | a system with only one CPU, say N. If you have a system with more | ||
| 193 | than one CPU, say Y. Note that the kernel does not currently | ||
| 194 | support SMP machines with 603/603e/603ev or PPC750 ("G3") processors | ||
| 195 | since they have inadequate hardware support for multiprocessor | ||
| 196 | operation. | ||
| 197 | |||
| 198 | If you say N here, the kernel will run on single and multiprocessor | ||
| 199 | machines, but will use only one CPU of a multiprocessor machine. If | ||
| 200 | you say Y here, the kernel will run on single-processor machines. | ||
| 201 | On a single-processor machine, the kernel will run faster if you say | ||
| 202 | N here. | ||
| 203 | |||
| 204 | If you don't know what to do here, say N. | ||
| 205 | |||
| 206 | config NR_CPUS | ||
| 207 | int "Maximum number of CPUs (2-128)" | ||
| 208 | range 2 128 | ||
| 209 | depends on SMP | ||
| 210 | default "32" if PPC64 | ||
| 211 | default "4" | ||
| 212 | |||
| 213 | config NOT_COHERENT_CACHE | ||
| 214 | bool | ||
| 215 | depends on 4xx || 8xx || E200 | ||
| 216 | default y | ||
| 217 | |||
| 218 | config CONFIG_CHECK_CACHE_COHERENCY | ||
| 219 | bool | ||
| 220 | |||
| 221 | endmenu | ||
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig deleted file mode 100644 index 6bde3bffed86..000000000000 --- a/arch/powerpc/platforms/apus/Kconfig +++ /dev/null | |||
| @@ -1,130 +0,0 @@ | |||
| 1 | |||
| 2 | config AMIGA | ||
| 3 | bool | ||
| 4 | depends on APUS | ||
| 5 | default y | ||
| 6 | help | ||
| 7 | This option enables support for the Amiga series of computers. | ||
| 8 | |||
| 9 | config ZORRO | ||
| 10 | bool | ||
| 11 | depends on APUS | ||
| 12 | default y | ||
| 13 | help | ||
| 14 | This enables support for the Zorro bus in the Amiga. If you have | ||
| 15 | expansion cards in your Amiga that conform to the Amiga | ||
| 16 | AutoConfig(tm) specification, say Y, otherwise N. Note that even | ||
| 17 | expansion cards that do not fit in the Zorro slots but fit in e.g. | ||
| 18 | the CPU slot may fall in this category, so you have to say Y to let | ||
| 19 | Linux use these. | ||
| 20 | |||
| 21 | config ABSTRACT_CONSOLE | ||
| 22 | bool | ||
| 23 | depends on APUS | ||
| 24 | default y | ||
| 25 | |||
| 26 | config APUS_FAST_EXCEPT | ||
| 27 | bool | ||
| 28 | depends on APUS | ||
| 29 | default y | ||
| 30 | |||
| 31 | config AMIGA_PCMCIA | ||
| 32 | bool "Amiga 1200/600 PCMCIA support" | ||
| 33 | depends on APUS && EXPERIMENTAL | ||
| 34 | help | ||
| 35 | Include support in the kernel for pcmcia on Amiga 1200 and Amiga | ||
| 36 | 600. If you intend to use pcmcia cards say Y; otherwise say N. | ||
| 37 | |||
| 38 | config AMIGA_BUILTIN_SERIAL | ||
| 39 | tristate "Amiga builtin serial support" | ||
| 40 | depends on APUS | ||
| 41 | help | ||
| 42 | If you want to use your Amiga's built-in serial port in Linux, | ||
| 43 | answer Y. | ||
| 44 | |||
| 45 | To compile this driver as a module, choose M here. | ||
| 46 | |||
| 47 | config GVPIOEXT | ||
| 48 | tristate "GVP IO-Extender support" | ||
| 49 | depends on APUS | ||
| 50 | help | ||
| 51 | If you want to use a GVP IO-Extender serial card in Linux, say Y. | ||
| 52 | Otherwise, say N. | ||
| 53 | |||
| 54 | config GVPIOEXT_LP | ||
| 55 | tristate "GVP IO-Extender parallel printer support" | ||
| 56 | depends on GVPIOEXT | ||
| 57 | help | ||
| 58 | Say Y to enable driving a printer from the parallel port on your | ||
| 59 | GVP IO-Extender card, N otherwise. | ||
| 60 | |||
| 61 | config GVPIOEXT_PLIP | ||
| 62 | tristate "GVP IO-Extender PLIP support" | ||
| 63 | depends on GVPIOEXT | ||
| 64 | help | ||
| 65 | Say Y to enable doing IP over the parallel port on your GVP | ||
| 66 | IO-Extender card, N otherwise. | ||
| 67 | |||
| 68 | config MULTIFACE_III_TTY | ||
| 69 | tristate "Multiface Card III serial support" | ||
| 70 | depends on APUS | ||
| 71 | help | ||
| 72 | If you want to use a Multiface III card's serial port in Linux, | ||
| 73 | answer Y. | ||
| 74 | |||
| 75 | To compile this driver as a module, choose M here. | ||
| 76 | |||
| 77 | config A2232 | ||
| 78 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" | ||
| 79 | depends on EXPERIMENTAL && APUS | ||
| 80 | ---help--- | ||
| 81 | This option supports the 2232 7-port serial card shipped with the | ||
| 82 | Amiga 2000 and other Zorro-bus machines, dating from 1989. At | ||
| 83 | a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip | ||
| 84 | each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The | ||
| 85 | ports were connected with 8 pin DIN connectors on the card bracket, | ||
| 86 | for which 8 pin to DB25 adapters were supplied. The card also had | ||
| 87 | jumpers internally to toggle various pinning configurations. | ||
| 88 | |||
| 89 | This driver can be built as a module; but then "generic_serial" | ||
| 90 | will also be built as a module. This has to be loaded before | ||
| 91 | "ser_a2232". If you want to do this, answer M here. | ||
| 92 | |||
| 93 | config WHIPPET_SERIAL | ||
| 94 | tristate "Hisoft Whippet PCMCIA serial support" | ||
| 95 | depends on AMIGA_PCMCIA | ||
| 96 | help | ||
| 97 | HiSoft has a web page at <http://www.hisoft.co.uk/>, but there | ||
| 98 | is no listing for the Whippet in their Amiga section. | ||
| 99 | |||
| 100 | config APNE | ||
| 101 | tristate "PCMCIA NE2000 support" | ||
| 102 | depends on AMIGA_PCMCIA | ||
| 103 | help | ||
| 104 | If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, | ||
| 105 | say N. | ||
| 106 | |||
| 107 | To compile this driver as a module, choose M here: the | ||
| 108 | module will be called apne. | ||
| 109 | |||
| 110 | config SERIAL_CONSOLE | ||
| 111 | bool "Support for serial port console" | ||
| 112 | depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y) | ||
| 113 | |||
| 114 | config HEARTBEAT | ||
| 115 | bool "Use power LED as a heartbeat" | ||
| 116 | depends on APUS | ||
| 117 | help | ||
| 118 | Use the power-on LED on your machine as a load meter. The exact | ||
| 119 | behavior is platform-dependent, but normally the flash frequency is | ||
| 120 | a hyperbolic function of the 5-minute load average. | ||
| 121 | |||
| 122 | config PROC_HARDWARE | ||
| 123 | bool "/proc/hardware support" | ||
| 124 | depends on APUS | ||
| 125 | |||
| 126 | source "drivers/zorro/Kconfig" | ||
| 127 | |||
| 128 | config PCI_PERMEDIA | ||
| 129 | bool "PCI for Permedia2" | ||
| 130 | depends on !4xx && !8xx && APUS | ||
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 7fb92f23f380..9d7c2ef940a8 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c | |||
| @@ -102,7 +102,7 @@ static void spider_io_flush(const volatile void __iomem *addr) | |||
| 102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | 102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); |
| 103 | 103 | ||
| 104 | /* Check if it's in allowed range for PIO */ | 104 | /* Check if it's in allowed range for PIO */ |
| 105 | if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE) | 105 | if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END) |
| 106 | return; | 106 | return; |
| 107 | 107 | ||
| 108 | /* Try to find a PTE. If not, clear the paddr, we'll do | 108 | /* Try to find a PTE. If not, clear the paddr, we'll do |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index a7f5a7653c62..e4d0c9f42abd 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
| @@ -183,7 +183,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
| 183 | spu->slb_replace = 0; | 183 | spu->slb_replace = 0; |
| 184 | 184 | ||
| 185 | spu_restart_dma(spu); | 185 | spu_restart_dma(spu); |
| 186 | 186 | spu->stats.slb_flt++; | |
| 187 | return 0; | 187 | return 0; |
| 188 | } | 188 | } |
| 189 | 189 | ||
| @@ -332,6 +332,7 @@ spu_irq_class_2(int irq, void *data) | |||
| 332 | if (stat & 0x10) /* SPU mailbox threshold */ | 332 | if (stat & 0x10) /* SPU mailbox threshold */ |
| 333 | spu->wbox_callback(spu); | 333 | spu->wbox_callback(spu); |
| 334 | 334 | ||
| 335 | spu->stats.class2_intr++; | ||
| 335 | return stat ? IRQ_HANDLED : IRQ_NONE; | 336 | return stat ? IRQ_HANDLED : IRQ_NONE; |
| 336 | } | 337 | } |
| 337 | 338 | ||
| @@ -462,8 +463,18 @@ void spu_free(struct spu *spu) | |||
| 462 | } | 463 | } |
| 463 | EXPORT_SYMBOL_GPL(spu_free); | 464 | EXPORT_SYMBOL_GPL(spu_free); |
| 464 | 465 | ||
| 466 | static int spu_shutdown(struct sys_device *sysdev) | ||
| 467 | { | ||
| 468 | struct spu *spu = container_of(sysdev, struct spu, sysdev); | ||
| 469 | |||
| 470 | spu_free_irqs(spu); | ||
| 471 | spu_destroy_spu(spu); | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 465 | struct sysdev_class spu_sysdev_class = { | 475 | struct sysdev_class spu_sysdev_class = { |
| 466 | set_kset_name("spu") | 476 | set_kset_name("spu"), |
| 477 | .shutdown = spu_shutdown, | ||
| 467 | }; | 478 | }; |
| 468 | 479 | ||
| 469 | int spu_add_sysdev_attr(struct sysdev_attribute *attr) | 480 | int spu_add_sysdev_attr(struct sysdev_attribute *attr) |
| @@ -574,6 +585,9 @@ static int __init create_spu(void *data) | |||
| 574 | spin_unlock_irqrestore(&spu_list_lock, flags); | 585 | spin_unlock_irqrestore(&spu_list_lock, flags); |
| 575 | mutex_unlock(&spu_mutex); | 586 | mutex_unlock(&spu_mutex); |
| 576 | 587 | ||
| 588 | spu->stats.utilization_state = SPU_UTIL_IDLE; | ||
| 589 | spu->stats.tstamp = jiffies; | ||
| 590 | |||
| 577 | goto out; | 591 | goto out; |
| 578 | 592 | ||
| 579 | out_free_irqs: | 593 | out_free_irqs: |
| @@ -586,6 +600,45 @@ out: | |||
| 586 | return ret; | 600 | return ret; |
| 587 | } | 601 | } |
| 588 | 602 | ||
| 603 | static const char *spu_state_names[] = { | ||
| 604 | "user", "system", "iowait", "idle" | ||
| 605 | }; | ||
| 606 | |||
| 607 | static unsigned long long spu_acct_time(struct spu *spu, | ||
| 608 | enum spu_utilization_state state) | ||
| 609 | { | ||
| 610 | unsigned long long time = spu->stats.times[state]; | ||
| 611 | |||
| 612 | if (spu->stats.utilization_state == state) | ||
| 613 | time += jiffies - spu->stats.tstamp; | ||
| 614 | |||
| 615 | return jiffies_to_msecs(time); | ||
| 616 | } | ||
| 617 | |||
| 618 | |||
| 619 | static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf) | ||
| 620 | { | ||
| 621 | struct spu *spu = container_of(sysdev, struct spu, sysdev); | ||
| 622 | |||
| 623 | return sprintf(buf, "%s %llu %llu %llu %llu " | ||
| 624 | "%llu %llu %llu %llu %llu %llu %llu %llu\n", | ||
| 625 | spu_state_names[spu->stats.utilization_state], | ||
| 626 | spu_acct_time(spu, SPU_UTIL_USER), | ||
| 627 | spu_acct_time(spu, SPU_UTIL_SYSTEM), | ||
| 628 | spu_acct_time(spu, SPU_UTIL_IOWAIT), | ||
| 629 | spu_acct_time(spu, SPU_UTIL_IDLE), | ||
| 630 | spu->stats.vol_ctx_switch, | ||
| 631 | spu->stats.invol_ctx_switch, | ||
| 632 | spu->stats.slb_flt, | ||
| 633 | spu->stats.hash_flt, | ||
| 634 | spu->stats.min_flt, | ||
| 635 | spu->stats.maj_flt, | ||
| 636 | spu->stats.class2_intr, | ||
| 637 | spu->stats.libassist); | ||
| 638 | } | ||
| 639 | |||
| 640 | static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); | ||
| 641 | |||
| 589 | static int __init init_spu_base(void) | 642 | static int __init init_spu_base(void) |
| 590 | { | 643 | { |
| 591 | int i, ret = 0; | 644 | int i, ret = 0; |
| @@ -611,6 +664,8 @@ static int __init init_spu_base(void) | |||
| 611 | 664 | ||
| 612 | xmon_register_spus(&spu_full_list); | 665 | xmon_register_spus(&spu_full_list); |
| 613 | 666 | ||
| 667 | spu_add_sysdev_attr(&attr_stat); | ||
| 668 | |||
| 614 | return 0; | 669 | return 0; |
| 615 | 670 | ||
| 616 | out_unregister_sysdev_class: | 671 | out_unregister_sysdev_class: |
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index d32db9ffc6eb..07a0e815abf5 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c | |||
| @@ -320,6 +320,12 @@ static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, | |||
| 320 | /* FIXME: what are the side-effects of this? */ | 320 | /* FIXME: what are the side-effects of this? */ |
| 321 | prob->dma_querymask_RW = mask; | 321 | prob->dma_querymask_RW = mask; |
| 322 | prob->dma_querytype_RW = mode; | 322 | prob->dma_querytype_RW = mode; |
| 323 | /* In the current implementation, the SPU context is always | ||
| 324 | * acquired in runnable state when new bits are added to the | ||
| 325 | * mask (tagwait), so it's sufficient just to mask | ||
| 326 | * dma_tagstatus_R with the 'mask' parameter here. | ||
| 327 | */ | ||
| 328 | ctx->csa.prob.dma_tagstatus_R &= mask; | ||
| 323 | out: | 329 | out: |
| 324 | spin_unlock(&ctx->csa.register_lock); | 330 | spin_unlock(&ctx->csa.register_lock); |
| 325 | 331 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 7c51cb54bca1..6d7bd60f5380 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
| @@ -23,10 +23,14 @@ | |||
| 23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
| 24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <asm/atomic.h> | ||
| 26 | #include <asm/spu.h> | 27 | #include <asm/spu.h> |
| 27 | #include <asm/spu_csa.h> | 28 | #include <asm/spu_csa.h> |
| 28 | #include "spufs.h" | 29 | #include "spufs.h" |
| 29 | 30 | ||
| 31 | |||
| 32 | atomic_t nr_spu_contexts = ATOMIC_INIT(0); | ||
| 33 | |||
| 30 | struct spu_context *alloc_spu_context(struct spu_gang *gang) | 34 | struct spu_context *alloc_spu_context(struct spu_gang *gang) |
| 31 | { | 35 | { |
| 32 | struct spu_context *ctx; | 36 | struct spu_context *ctx; |
| @@ -53,10 +57,12 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
| 53 | INIT_LIST_HEAD(&ctx->rq); | 57 | INIT_LIST_HEAD(&ctx->rq); |
| 54 | if (gang) | 58 | if (gang) |
| 55 | spu_gang_add_ctx(gang, ctx); | 59 | spu_gang_add_ctx(gang, ctx); |
| 56 | ctx->rt_priority = current->rt_priority; | 60 | ctx->cpus_allowed = current->cpus_allowed; |
| 57 | ctx->policy = current->policy; | 61 | spu_set_timeslice(ctx); |
| 58 | ctx->prio = current->prio; | 62 | ctx->stats.execution_state = SPUCTX_UTIL_USER; |
| 59 | INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick); | 63 | ctx->stats.tstamp = jiffies; |
| 64 | |||
| 65 | atomic_inc(&nr_spu_contexts); | ||
| 60 | goto out; | 66 | goto out; |
| 61 | out_free: | 67 | out_free: |
| 62 | kfree(ctx); | 68 | kfree(ctx); |
| @@ -76,6 +82,7 @@ void destroy_spu_context(struct kref *kref) | |||
| 76 | if (ctx->gang) | 82 | if (ctx->gang) |
| 77 | spu_gang_remove_ctx(ctx->gang, ctx); | 83 | spu_gang_remove_ctx(ctx->gang, ctx); |
| 78 | BUG_ON(!list_empty(&ctx->rq)); | 84 | BUG_ON(!list_empty(&ctx->rq)); |
| 85 | atomic_dec(&nr_spu_contexts); | ||
| 79 | kfree(ctx); | 86 | kfree(ctx); |
| 80 | } | 87 | } |
| 81 | 88 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index 0f75c07e29d8..e064d0c0d80e 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c | |||
| @@ -33,7 +33,8 @@ | |||
| 33 | * function. Currently, there are a few corner cases that we haven't had | 33 | * function. Currently, there are a few corner cases that we haven't had |
| 34 | * to handle fortunately. | 34 | * to handle fortunately. |
| 35 | */ | 35 | */ |
| 36 | static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) | 36 | static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, |
| 37 | unsigned long dsisr, unsigned *flt) | ||
| 37 | { | 38 | { |
| 38 | struct vm_area_struct *vma; | 39 | struct vm_area_struct *vma; |
| 39 | unsigned long is_write; | 40 | unsigned long is_write; |
| @@ -73,7 +74,8 @@ good_area: | |||
| 73 | goto bad_area; | 74 | goto bad_area; |
| 74 | } | 75 | } |
| 75 | ret = 0; | 76 | ret = 0; |
| 76 | switch (handle_mm_fault(mm, vma, ea, is_write)) { | 77 | *flt = handle_mm_fault(mm, vma, ea, is_write); |
| 78 | switch (*flt) { | ||
| 77 | case VM_FAULT_MINOR: | 79 | case VM_FAULT_MINOR: |
| 78 | current->min_flt++; | 80 | current->min_flt++; |
| 79 | break; | 81 | break; |
| @@ -153,6 +155,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
| 153 | { | 155 | { |
| 154 | u64 ea, dsisr, access; | 156 | u64 ea, dsisr, access; |
| 155 | unsigned long flags; | 157 | unsigned long flags; |
| 158 | unsigned flt = 0; | ||
| 156 | int ret; | 159 | int ret; |
| 157 | 160 | ||
| 158 | /* | 161 | /* |
| @@ -178,9 +181,17 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
| 178 | if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) | 181 | if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) |
| 179 | return 0; | 182 | return 0; |
| 180 | 183 | ||
| 184 | spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT); | ||
| 185 | |||
| 181 | pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, | 186 | pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, |
| 182 | dsisr, ctx->state); | 187 | dsisr, ctx->state); |
| 183 | 188 | ||
| 189 | ctx->stats.hash_flt++; | ||
| 190 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
| 191 | ctx->spu->stats.hash_flt++; | ||
| 192 | spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT); | ||
| 193 | } | ||
| 194 | |||
| 184 | /* we must not hold the lock when entering spu_handle_mm_fault */ | 195 | /* we must not hold the lock when entering spu_handle_mm_fault */ |
| 185 | spu_release(ctx); | 196 | spu_release(ctx); |
| 186 | 197 | ||
| @@ -192,7 +203,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
| 192 | 203 | ||
| 193 | /* hashing failed, so try the actual fault handler */ | 204 | /* hashing failed, so try the actual fault handler */ |
| 194 | if (ret) | 205 | if (ret) |
| 195 | ret = spu_handle_mm_fault(current->mm, ea, dsisr); | 206 | ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); |
| 196 | 207 | ||
| 197 | spu_acquire(ctx); | 208 | spu_acquire(ctx); |
| 198 | /* | 209 | /* |
| @@ -201,11 +212,23 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
| 201 | * In case of unhandled error report the problem to user space. | 212 | * In case of unhandled error report the problem to user space. |
| 202 | */ | 213 | */ |
| 203 | if (!ret) { | 214 | if (!ret) { |
| 215 | if (flt == VM_FAULT_MINOR) | ||
| 216 | ctx->stats.min_flt++; | ||
| 217 | else | ||
| 218 | ctx->stats.maj_flt++; | ||
| 219 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
| 220 | if (flt == VM_FAULT_MINOR) | ||
| 221 | ctx->spu->stats.min_flt++; | ||
| 222 | else | ||
| 223 | ctx->spu->stats.maj_flt++; | ||
| 224 | } | ||
| 225 | |||
| 204 | if (ctx->spu) | 226 | if (ctx->spu) |
| 205 | ctx->ops->restart_dma(ctx); | 227 | ctx->ops->restart_dma(ctx); |
| 206 | } else | 228 | } else |
| 207 | spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); | 229 | spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); |
| 208 | 230 | ||
| 231 | spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); | ||
| 209 | return ret; | 232 | return ret; |
| 210 | } | 233 | } |
| 211 | EXPORT_SYMBOL_GPL(spufs_handle_class1); | 234 | EXPORT_SYMBOL_GPL(spufs_handle_class1); |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index b1e7e2f8a2e9..c2814ea96af2 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/pagemap.h> | 28 | #include <linux/pagemap.h> |
| 29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
| 30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
| 31 | #include <linux/seq_file.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
| 33 | #include <asm/semaphore.h> | 34 | #include <asm/semaphore.h> |
| @@ -39,6 +40,7 @@ | |||
| 39 | 40 | ||
| 40 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) | 41 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) |
| 41 | 42 | ||
| 43 | |||
| 42 | static int | 44 | static int |
| 43 | spufs_mem_open(struct inode *inode, struct file *file) | 45 | spufs_mem_open(struct inode *inode, struct file *file) |
| 44 | { | 46 | { |
| @@ -216,12 +218,12 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 216 | #endif /* CONFIG_SPU_FS_64K_LS */ | 218 | #endif /* CONFIG_SPU_FS_64K_LS */ |
| 217 | 219 | ||
| 218 | static const struct file_operations spufs_mem_fops = { | 220 | static const struct file_operations spufs_mem_fops = { |
| 219 | .open = spufs_mem_open, | 221 | .open = spufs_mem_open, |
| 220 | .release = spufs_mem_release, | 222 | .release = spufs_mem_release, |
| 221 | .read = spufs_mem_read, | 223 | .read = spufs_mem_read, |
| 222 | .write = spufs_mem_write, | 224 | .write = spufs_mem_write, |
| 223 | .llseek = generic_file_llseek, | 225 | .llseek = generic_file_llseek, |
| 224 | .mmap = spufs_mem_mmap, | 226 | .mmap = spufs_mem_mmap, |
| 225 | #ifdef CONFIG_SPU_FS_64K_LS | 227 | #ifdef CONFIG_SPU_FS_64K_LS |
| 226 | .get_unmapped_area = spufs_get_unmapped_area, | 228 | .get_unmapped_area = spufs_get_unmapped_area, |
| 227 | #endif | 229 | #endif |
| @@ -1497,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | |||
| 1497 | if (status) | 1499 | if (status) |
| 1498 | ret = status; | 1500 | ret = status; |
| 1499 | } | 1501 | } |
| 1500 | spu_release(ctx); | ||
| 1501 | 1502 | ||
| 1502 | if (ret) | 1503 | if (ret) |
| 1503 | goto out; | 1504 | goto out_unlock; |
| 1504 | 1505 | ||
| 1505 | ctx->tagwait |= 1 << cmd.tag; | 1506 | ctx->tagwait |= 1 << cmd.tag; |
| 1506 | ret = size; | 1507 | ret = size; |
| 1507 | 1508 | ||
| 1509 | out_unlock: | ||
| 1510 | spu_release(ctx); | ||
| 1508 | out: | 1511 | out: |
| 1509 | return ret; | 1512 | return ret; |
| 1510 | } | 1513 | } |
| @@ -1515,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) | |||
| 1515 | u32 free_elements, tagstatus; | 1518 | u32 free_elements, tagstatus; |
| 1516 | unsigned int mask; | 1519 | unsigned int mask; |
| 1517 | 1520 | ||
| 1521 | poll_wait(file, &ctx->mfc_wq, wait); | ||
| 1522 | |||
| 1518 | spu_acquire(ctx); | 1523 | spu_acquire(ctx); |
| 1519 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); | 1524 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); |
| 1520 | free_elements = ctx->ops->get_mfc_free_elements(ctx); | 1525 | free_elements = ctx->ops->get_mfc_free_elements(ctx); |
| 1521 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); | 1526 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); |
| 1522 | spu_release(ctx); | 1527 | spu_release(ctx); |
| 1523 | 1528 | ||
| 1524 | poll_wait(file, &ctx->mfc_wq, wait); | ||
| 1525 | |||
| 1526 | mask = 0; | 1529 | mask = 0; |
| 1527 | if (free_elements & 0xffff) | 1530 | if (free_elements & 0xffff) |
| 1528 | mask |= POLLOUT | POLLWRNORM; | 1531 | mask |= POLLOUT | POLLWRNORM; |
| @@ -1797,6 +1800,29 @@ static int spufs_info_open(struct inode *inode, struct file *file) | |||
| 1797 | return 0; | 1800 | return 0; |
| 1798 | } | 1801 | } |
| 1799 | 1802 | ||
| 1803 | static int spufs_caps_show(struct seq_file *s, void *private) | ||
| 1804 | { | ||
| 1805 | struct spu_context *ctx = s->private; | ||
| 1806 | |||
| 1807 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) | ||
| 1808 | seq_puts(s, "sched\n"); | ||
| 1809 | if (!(ctx->flags & SPU_CREATE_ISOLATE)) | ||
| 1810 | seq_puts(s, "step\n"); | ||
| 1811 | return 0; | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | static int spufs_caps_open(struct inode *inode, struct file *file) | ||
| 1815 | { | ||
| 1816 | return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | static const struct file_operations spufs_caps_fops = { | ||
| 1820 | .open = spufs_caps_open, | ||
| 1821 | .read = seq_read, | ||
| 1822 | .llseek = seq_lseek, | ||
| 1823 | .release = single_release, | ||
| 1824 | }; | ||
| 1825 | |||
| 1800 | static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, | 1826 | static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, |
| 1801 | char __user *buf, size_t len, loff_t *pos) | 1827 | char __user *buf, size_t len, loff_t *pos) |
| 1802 | { | 1828 | { |
| @@ -2014,7 +2040,105 @@ static const struct file_operations spufs_proxydma_info_fops = { | |||
| 2014 | .read = spufs_proxydma_info_read, | 2040 | .read = spufs_proxydma_info_read, |
| 2015 | }; | 2041 | }; |
| 2016 | 2042 | ||
| 2043 | static int spufs_show_tid(struct seq_file *s, void *private) | ||
| 2044 | { | ||
| 2045 | struct spu_context *ctx = s->private; | ||
| 2046 | |||
| 2047 | seq_printf(s, "%d\n", ctx->tid); | ||
| 2048 | return 0; | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | static int spufs_tid_open(struct inode *inode, struct file *file) | ||
| 2052 | { | ||
| 2053 | return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx); | ||
| 2054 | } | ||
| 2055 | |||
| 2056 | static const struct file_operations spufs_tid_fops = { | ||
| 2057 | .open = spufs_tid_open, | ||
| 2058 | .read = seq_read, | ||
| 2059 | .llseek = seq_lseek, | ||
| 2060 | .release = single_release, | ||
| 2061 | }; | ||
| 2062 | |||
| 2063 | static const char *ctx_state_names[] = { | ||
| 2064 | "user", "system", "iowait", "loaded" | ||
| 2065 | }; | ||
| 2066 | |||
| 2067 | static unsigned long long spufs_acct_time(struct spu_context *ctx, | ||
| 2068 | enum spuctx_execution_state state) | ||
| 2069 | { | ||
| 2070 | unsigned long time = ctx->stats.times[state]; | ||
| 2071 | |||
| 2072 | if (ctx->stats.execution_state == state) | ||
| 2073 | time += jiffies - ctx->stats.tstamp; | ||
| 2074 | |||
| 2075 | return jiffies_to_msecs(time); | ||
| 2076 | } | ||
| 2077 | |||
| 2078 | static unsigned long long spufs_slb_flts(struct spu_context *ctx) | ||
| 2079 | { | ||
| 2080 | unsigned long long slb_flts = ctx->stats.slb_flt; | ||
| 2081 | |||
| 2082 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
| 2083 | slb_flts += (ctx->spu->stats.slb_flt - | ||
| 2084 | ctx->stats.slb_flt_base); | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | return slb_flts; | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | static unsigned long long spufs_class2_intrs(struct spu_context *ctx) | ||
| 2091 | { | ||
| 2092 | unsigned long long class2_intrs = ctx->stats.class2_intr; | ||
| 2093 | |||
| 2094 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
| 2095 | class2_intrs += (ctx->spu->stats.class2_intr - | ||
| 2096 | ctx->stats.class2_intr_base); | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | return class2_intrs; | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | |||
| 2103 | static int spufs_show_stat(struct seq_file *s, void *private) | ||
| 2104 | { | ||
| 2105 | struct spu_context *ctx = s->private; | ||
| 2106 | |||
| 2107 | spu_acquire(ctx); | ||
| 2108 | seq_printf(s, "%s %llu %llu %llu %llu " | ||
| 2109 | "%llu %llu %llu %llu %llu %llu %llu %llu\n", | ||
| 2110 | ctx_state_names[ctx->stats.execution_state], | ||
| 2111 | spufs_acct_time(ctx, SPUCTX_UTIL_USER), | ||
| 2112 | spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM), | ||
| 2113 | spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT), | ||
| 2114 | spufs_acct_time(ctx, SPUCTX_UTIL_LOADED), | ||
| 2115 | ctx->stats.vol_ctx_switch, | ||
| 2116 | ctx->stats.invol_ctx_switch, | ||
| 2117 | spufs_slb_flts(ctx), | ||
| 2118 | ctx->stats.hash_flt, | ||
| 2119 | ctx->stats.min_flt, | ||
| 2120 | ctx->stats.maj_flt, | ||
| 2121 | spufs_class2_intrs(ctx), | ||
| 2122 | ctx->stats.libassist); | ||
| 2123 | spu_release(ctx); | ||
| 2124 | return 0; | ||
| 2125 | } | ||
| 2126 | |||
| 2127 | static int spufs_stat_open(struct inode *inode, struct file *file) | ||
| 2128 | { | ||
| 2129 | return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx); | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | static const struct file_operations spufs_stat_fops = { | ||
| 2133 | .open = spufs_stat_open, | ||
| 2134 | .read = seq_read, | ||
| 2135 | .llseek = seq_lseek, | ||
| 2136 | .release = single_release, | ||
| 2137 | }; | ||
| 2138 | |||
| 2139 | |||
| 2017 | struct tree_descr spufs_dir_contents[] = { | 2140 | struct tree_descr spufs_dir_contents[] = { |
| 2141 | { "capabilities", &spufs_caps_fops, 0444, }, | ||
| 2018 | { "mem", &spufs_mem_fops, 0666, }, | 2142 | { "mem", &spufs_mem_fops, 0666, }, |
| 2019 | { "regs", &spufs_regs_fops, 0666, }, | 2143 | { "regs", &spufs_regs_fops, 0666, }, |
| 2020 | { "mbox", &spufs_mbox_fops, 0444, }, | 2144 | { "mbox", &spufs_mbox_fops, 0444, }, |
| @@ -2046,10 +2170,13 @@ struct tree_descr spufs_dir_contents[] = { | |||
| 2046 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, | 2170 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, |
| 2047 | { "dma_info", &spufs_dma_info_fops, 0444, }, | 2171 | { "dma_info", &spufs_dma_info_fops, 0444, }, |
| 2048 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, | 2172 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, |
| 2173 | { "tid", &spufs_tid_fops, 0444, }, | ||
| 2174 | { "stat", &spufs_stat_fops, 0444, }, | ||
| 2049 | {}, | 2175 | {}, |
| 2050 | }; | 2176 | }; |
| 2051 | 2177 | ||
| 2052 | struct tree_descr spufs_dir_nosched_contents[] = { | 2178 | struct tree_descr spufs_dir_nosched_contents[] = { |
| 2179 | { "capabilities", &spufs_caps_fops, 0444, }, | ||
| 2053 | { "mem", &spufs_mem_fops, 0666, }, | 2180 | { "mem", &spufs_mem_fops, 0666, }, |
| 2054 | { "mbox", &spufs_mbox_fops, 0444, }, | 2181 | { "mbox", &spufs_mbox_fops, 0444, }, |
| 2055 | { "ibox", &spufs_ibox_fops, 0444, }, | 2182 | { "ibox", &spufs_ibox_fops, 0444, }, |
| @@ -2068,6 +2195,8 @@ struct tree_descr spufs_dir_nosched_contents[] = { | |||
| 2068 | { "psmap", &spufs_psmap_fops, 0666, }, | 2195 | { "psmap", &spufs_psmap_fops, 0666, }, |
| 2069 | { "phys-id", &spufs_id_ops, 0666, }, | 2196 | { "phys-id", &spufs_id_ops, 0666, }, |
| 2070 | { "object-id", &spufs_object_id_ops, 0666, }, | 2197 | { "object-id", &spufs_object_id_ops, 0666, }, |
| 2198 | { "tid", &spufs_tid_fops, 0444, }, | ||
| 2199 | { "stat", &spufs_stat_fops, 0444, }, | ||
| 2071 | {}, | 2200 | {}, |
| 2072 | }; | 2201 | }; |
| 2073 | 2202 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 9807206e0219..f37460e5bfd2 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -232,10 +232,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file) | |||
| 232 | return dcache_dir_close(inode, file); | 232 | return dcache_dir_close(inode, file); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | const struct inode_operations spufs_dir_inode_operations = { | ||
| 236 | .lookup = simple_lookup, | ||
| 237 | }; | ||
| 238 | |||
| 239 | const struct file_operations spufs_context_fops = { | 235 | const struct file_operations spufs_context_fops = { |
| 240 | .open = dcache_dir_open, | 236 | .open = dcache_dir_open, |
| 241 | .release = spufs_dir_close, | 237 | .release = spufs_dir_close, |
| @@ -269,7 +265,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
| 269 | goto out_iput; | 265 | goto out_iput; |
| 270 | 266 | ||
| 271 | ctx->flags = flags; | 267 | ctx->flags = flags; |
| 272 | inode->i_op = &spufs_dir_inode_operations; | 268 | inode->i_op = &simple_dir_inode_operations; |
| 273 | inode->i_fop = &simple_dir_operations; | 269 | inode->i_fop = &simple_dir_operations; |
| 274 | if (flags & SPU_CREATE_NOSCHED) | 270 | if (flags & SPU_CREATE_NOSCHED) |
| 275 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, | 271 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, |
| @@ -386,7 +382,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) | |||
| 386 | if (!gang) | 382 | if (!gang) |
| 387 | goto out_iput; | 383 | goto out_iput; |
| 388 | 384 | ||
| 389 | inode->i_op = &spufs_dir_inode_operations; | 385 | inode->i_op = &simple_dir_inode_operations; |
| 390 | inode->i_fop = &simple_dir_operations; | 386 | inode->i_fop = &simple_dir_operations; |
| 391 | 387 | ||
| 392 | d_instantiate(dentry, inode); | 388 | d_instantiate(dentry, inode); |
| @@ -593,7 +589,7 @@ spufs_create_root(struct super_block *sb, void *data) | |||
| 593 | if (!inode) | 589 | if (!inode) |
| 594 | goto out; | 590 | goto out; |
| 595 | 591 | ||
| 596 | inode->i_op = &spufs_dir_inode_operations; | 592 | inode->i_op = &simple_dir_inode_operations; |
| 597 | inode->i_fop = &simple_dir_operations; | 593 | inode->i_fop = &simple_dir_operations; |
| 598 | SPUFS_I(inode)->i_ctx = NULL; | 594 | SPUFS_I(inode)->i_ctx = NULL; |
| 599 | 595 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 57626600b1a4..58ae13b7de84 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
| @@ -29,7 +29,8 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | |||
| 29 | spu = ctx->spu; | 29 | spu = ctx->spu; |
| 30 | pte_fault = spu->dsisr & | 30 | pte_fault = spu->dsisr & |
| 31 | (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); | 31 | (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); |
| 32 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; | 32 | return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ? |
| 33 | 1 : 0; | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | static int spu_setup_isolated(struct spu_context *ctx) | 36 | static int spu_setup_isolated(struct spu_context *ctx) |
| @@ -142,8 +143,11 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc) | |||
| 142 | runcntl = SPU_RUNCNTL_RUNNABLE; | 143 | runcntl = SPU_RUNCNTL_RUNNABLE; |
| 143 | ctx->ops->runcntl_write(ctx, runcntl); | 144 | ctx->ops->runcntl_write(ctx, runcntl); |
| 144 | } else { | 145 | } else { |
| 145 | spu_start_tick(ctx); | 146 | unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL; |
| 146 | ctx->ops->npc_write(ctx, *npc); | 147 | ctx->ops->npc_write(ctx, *npc); |
| 148 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
| 149 | mode = SPU_PRIVCNTL_MODE_SINGLE_STEP; | ||
| 150 | out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode); | ||
| 147 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | 151 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); |
| 148 | } | 152 | } |
| 149 | 153 | ||
| @@ -155,7 +159,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc, | |||
| 155 | { | 159 | { |
| 156 | int ret = 0; | 160 | int ret = 0; |
| 157 | 161 | ||
| 158 | spu_stop_tick(ctx); | ||
| 159 | *status = ctx->ops->status_read(ctx); | 162 | *status = ctx->ops->status_read(ctx); |
| 160 | *npc = ctx->ops->npc_read(ctx); | 163 | *npc = ctx->ops->npc_read(ctx); |
| 161 | spu_release(ctx); | 164 | spu_release(ctx); |
| @@ -298,9 +301,22 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
| 298 | ctx->ops->master_start(ctx); | 301 | ctx->ops->master_start(ctx); |
| 299 | ctx->event_return = 0; | 302 | ctx->event_return = 0; |
| 300 | 303 | ||
| 301 | ret = spu_acquire_runnable(ctx, 0); | 304 | spu_acquire(ctx); |
| 302 | if (ret) | 305 | if (ctx->state == SPU_STATE_SAVED) { |
| 303 | return ret; | 306 | __spu_update_sched_info(ctx); |
| 307 | |||
| 308 | ret = spu_activate(ctx, 0); | ||
| 309 | if (ret) { | ||
| 310 | spu_release(ctx); | ||
| 311 | goto out; | ||
| 312 | } | ||
| 313 | } else { | ||
| 314 | /* | ||
| 315 | * We have to update the scheduling priority under active_mutex | ||
| 316 | * to protect against find_victim(). | ||
| 317 | */ | ||
| 318 | spu_update_sched_info(ctx); | ||
| 319 | } | ||
| 304 | 320 | ||
| 305 | ret = spu_run_init(ctx, npc); | 321 | ret = spu_run_init(ctx, npc); |
| 306 | if (ret) { | 322 | if (ret) { |
| @@ -325,16 +341,20 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
| 325 | 341 | ||
| 326 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 342 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
| 327 | ret = spu_reacquire_runnable(ctx, npc, &status); | 343 | ret = spu_reacquire_runnable(ctx, npc, &status); |
| 328 | if (ret) { | 344 | if (ret) |
| 329 | spu_stop_tick(ctx); | ||
| 330 | goto out2; | 345 | goto out2; |
| 331 | } | ||
| 332 | continue; | 346 | continue; |
| 333 | } | 347 | } |
| 334 | ret = spu_process_events(ctx); | 348 | ret = spu_process_events(ctx); |
| 335 | 349 | ||
| 336 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | | 350 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | |
| 337 | SPU_STATUS_STOPPED_BY_HALT))); | 351 | SPU_STATUS_STOPPED_BY_HALT | |
| 352 | SPU_STATUS_SINGLE_STEP))); | ||
| 353 | |||
| 354 | if ((status & SPU_STATUS_STOPPED_BY_STOP) && | ||
| 355 | (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) && | ||
| 356 | (ctx->state == SPU_STATE_RUNNABLE)) | ||
| 357 | ctx->stats.libassist++; | ||
| 338 | 358 | ||
| 339 | ctx->ops->master_stop(ctx); | 359 | ctx->ops->master_stop(ctx); |
| 340 | ret = spu_run_fini(ctx, npc, &status); | 360 | ret = spu_run_fini(ctx, npc, &status); |
| @@ -344,10 +364,15 @@ out2: | |||
| 344 | if ((ret == 0) || | 364 | if ((ret == 0) || |
| 345 | ((ret == -ERESTARTSYS) && | 365 | ((ret == -ERESTARTSYS) && |
| 346 | ((status & SPU_STATUS_STOPPED_BY_HALT) || | 366 | ((status & SPU_STATUS_STOPPED_BY_HALT) || |
| 367 | (status & SPU_STATUS_SINGLE_STEP) || | ||
| 347 | ((status & SPU_STATUS_STOPPED_BY_STOP) && | 368 | ((status & SPU_STATUS_STOPPED_BY_STOP) && |
| 348 | (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) | 369 | (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) |
| 349 | ret = status; | 370 | ret = status; |
| 350 | 371 | ||
| 372 | /* Note: we don't need to force_sig SIGTRAP on single-step | ||
| 373 | * since we have TIF_SINGLESTEP set, thus the kernel will do | ||
| 374 | * it upon return from the syscall anyawy | ||
| 375 | */ | ||
| 351 | if ((status & SPU_STATUS_STOPPED_BY_STOP) | 376 | if ((status & SPU_STATUS_STOPPED_BY_STOP) |
| 352 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | 377 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { |
| 353 | force_sig(SIGTRAP, current); | 378 | force_sig(SIGTRAP, current); |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 3b831e07f1ed..e5b4dd1db286 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
| @@ -35,6 +35,10 @@ | |||
| 35 | #include <linux/numa.h> | 35 | #include <linux/numa.h> |
| 36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
| 37 | #include <linux/notifier.h> | 37 | #include <linux/notifier.h> |
| 38 | #include <linux/kthread.h> | ||
| 39 | #include <linux/pid_namespace.h> | ||
| 40 | #include <linux/proc_fs.h> | ||
| 41 | #include <linux/seq_file.h> | ||
| 38 | 42 | ||
| 39 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 40 | #include <asm/mmu_context.h> | 44 | #include <asm/mmu_context.h> |
| @@ -43,54 +47,126 @@ | |||
| 43 | #include <asm/spu_priv1.h> | 47 | #include <asm/spu_priv1.h> |
| 44 | #include "spufs.h" | 48 | #include "spufs.h" |
| 45 | 49 | ||
| 46 | #define SPU_TIMESLICE (HZ) | ||
| 47 | |||
| 48 | struct spu_prio_array { | 50 | struct spu_prio_array { |
| 49 | DECLARE_BITMAP(bitmap, MAX_PRIO); | 51 | DECLARE_BITMAP(bitmap, MAX_PRIO); |
| 50 | struct list_head runq[MAX_PRIO]; | 52 | struct list_head runq[MAX_PRIO]; |
| 51 | spinlock_t runq_lock; | 53 | spinlock_t runq_lock; |
| 52 | struct list_head active_list[MAX_NUMNODES]; | 54 | struct list_head active_list[MAX_NUMNODES]; |
| 53 | struct mutex active_mutex[MAX_NUMNODES]; | 55 | struct mutex active_mutex[MAX_NUMNODES]; |
| 56 | int nr_active[MAX_NUMNODES]; | ||
| 57 | int nr_waiting; | ||
| 54 | }; | 58 | }; |
| 55 | 59 | ||
| 60 | static unsigned long spu_avenrun[3]; | ||
| 56 | static struct spu_prio_array *spu_prio; | 61 | static struct spu_prio_array *spu_prio; |
| 57 | static struct workqueue_struct *spu_sched_wq; | 62 | static struct task_struct *spusched_task; |
| 63 | static struct timer_list spusched_timer; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). | ||
| 67 | */ | ||
| 68 | #define NORMAL_PRIO 120 | ||
| 69 | |||
| 70 | /* | ||
| 71 | * Frequency of the spu scheduler tick. By default we do one SPU scheduler | ||
| 72 | * tick for every 10 CPU scheduler ticks. | ||
| 73 | */ | ||
| 74 | #define SPUSCHED_TICK (10) | ||
| 58 | 75 | ||
| 59 | static inline int node_allowed(int node) | 76 | /* |
| 77 | * These are the 'tuning knobs' of the scheduler: | ||
| 78 | * | ||
| 79 | * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is | ||
| 80 | * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs. | ||
| 81 | */ | ||
| 82 | #define MIN_SPU_TIMESLICE max(5 * HZ / (1000 * SPUSCHED_TICK), 1) | ||
| 83 | #define DEF_SPU_TIMESLICE (100 * HZ / (1000 * SPUSCHED_TICK)) | ||
| 84 | |||
| 85 | #define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO) | ||
| 86 | #define SCALE_PRIO(x, prio) \ | ||
| 87 | max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE) | ||
| 88 | |||
| 89 | /* | ||
| 90 | * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values: | ||
| 91 | * [800ms ... 100ms ... 5ms] | ||
| 92 | * | ||
| 93 | * The higher a thread's priority, the bigger timeslices | ||
| 94 | * it gets during one round of execution. But even the lowest | ||
| 95 | * priority thread gets MIN_TIMESLICE worth of execution time. | ||
| 96 | */ | ||
| 97 | void spu_set_timeslice(struct spu_context *ctx) | ||
| 60 | { | 98 | { |
| 61 | cpumask_t mask; | 99 | if (ctx->prio < NORMAL_PRIO) |
| 100 | ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio); | ||
| 101 | else | ||
| 102 | ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio); | ||
| 103 | } | ||
| 62 | 104 | ||
| 63 | if (!nr_cpus_node(node)) | 105 | /* |
| 64 | return 0; | 106 | * Update scheduling information from the owning thread. |
| 65 | mask = node_to_cpumask(node); | 107 | */ |
| 66 | if (!cpus_intersects(mask, current->cpus_allowed)) | 108 | void __spu_update_sched_info(struct spu_context *ctx) |
| 67 | return 0; | 109 | { |
| 68 | return 1; | 110 | /* |
| 111 | * 32-Bit assignment are atomic on powerpc, and we don't care about | ||
| 112 | * memory ordering here because retriving the controlling thread is | ||
| 113 | * per defintion racy. | ||
| 114 | */ | ||
| 115 | ctx->tid = current->pid; | ||
| 116 | |||
| 117 | /* | ||
| 118 | * We do our own priority calculations, so we normally want | ||
| 119 | * ->static_prio to start with. Unfortunately thies field | ||
| 120 | * contains junk for threads with a realtime scheduling | ||
| 121 | * policy so we have to look at ->prio in this case. | ||
| 122 | */ | ||
| 123 | if (rt_prio(current->prio)) | ||
| 124 | ctx->prio = current->prio; | ||
| 125 | else | ||
| 126 | ctx->prio = current->static_prio; | ||
| 127 | ctx->policy = current->policy; | ||
| 128 | |||
| 129 | /* | ||
| 130 | * A lot of places that don't hold active_mutex poke into | ||
| 131 | * cpus_allowed, including grab_runnable_context which | ||
| 132 | * already holds the runq_lock. So abuse runq_lock | ||
| 133 | * to protect this field aswell. | ||
| 134 | */ | ||
| 135 | spin_lock(&spu_prio->runq_lock); | ||
| 136 | ctx->cpus_allowed = current->cpus_allowed; | ||
| 137 | spin_unlock(&spu_prio->runq_lock); | ||
| 69 | } | 138 | } |
| 70 | 139 | ||
| 71 | void spu_start_tick(struct spu_context *ctx) | 140 | void spu_update_sched_info(struct spu_context *ctx) |
| 72 | { | 141 | { |
| 73 | if (ctx->policy == SCHED_RR) { | 142 | int node = ctx->spu->node; |
| 74 | /* | 143 | |
| 75 | * Make sure the exiting bit is cleared. | 144 | mutex_lock(&spu_prio->active_mutex[node]); |
| 76 | */ | 145 | __spu_update_sched_info(ctx); |
| 77 | clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); | 146 | mutex_unlock(&spu_prio->active_mutex[node]); |
| 78 | mb(); | ||
| 79 | queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); | ||
| 80 | } | ||
| 81 | } | 147 | } |
| 82 | 148 | ||
| 83 | void spu_stop_tick(struct spu_context *ctx) | 149 | static int __node_allowed(struct spu_context *ctx, int node) |
| 84 | { | 150 | { |
| 85 | if (ctx->policy == SCHED_RR) { | 151 | if (nr_cpus_node(node)) { |
| 86 | /* | 152 | cpumask_t mask = node_to_cpumask(node); |
| 87 | * While the work can be rearming normally setting this flag | 153 | |
| 88 | * makes sure it does not rearm itself anymore. | 154 | if (cpus_intersects(mask, ctx->cpus_allowed)) |
| 89 | */ | 155 | return 1; |
| 90 | set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); | ||
| 91 | mb(); | ||
| 92 | cancel_delayed_work(&ctx->sched_work); | ||
| 93 | } | 156 | } |
| 157 | |||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int node_allowed(struct spu_context *ctx, int node) | ||
| 162 | { | ||
| 163 | int rval; | ||
| 164 | |||
| 165 | spin_lock(&spu_prio->runq_lock); | ||
| 166 | rval = __node_allowed(ctx, node); | ||
| 167 | spin_unlock(&spu_prio->runq_lock); | ||
| 168 | |||
| 169 | return rval; | ||
| 94 | } | 170 | } |
| 95 | 171 | ||
| 96 | /** | 172 | /** |
| @@ -99,9 +175,18 @@ void spu_stop_tick(struct spu_context *ctx) | |||
| 99 | */ | 175 | */ |
| 100 | static void spu_add_to_active_list(struct spu *spu) | 176 | static void spu_add_to_active_list(struct spu *spu) |
| 101 | { | 177 | { |
| 102 | mutex_lock(&spu_prio->active_mutex[spu->node]); | 178 | int node = spu->node; |
| 103 | list_add_tail(&spu->list, &spu_prio->active_list[spu->node]); | 179 | |
| 104 | mutex_unlock(&spu_prio->active_mutex[spu->node]); | 180 | mutex_lock(&spu_prio->active_mutex[node]); |
| 181 | spu_prio->nr_active[node]++; | ||
| 182 | list_add_tail(&spu->list, &spu_prio->active_list[node]); | ||
| 183 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void __spu_remove_from_active_list(struct spu *spu) | ||
| 187 | { | ||
| 188 | list_del_init(&spu->list); | ||
| 189 | spu_prio->nr_active[spu->node]--; | ||
| 105 | } | 190 | } |
| 106 | 191 | ||
| 107 | /** | 192 | /** |
| @@ -113,7 +198,7 @@ static void spu_remove_from_active_list(struct spu *spu) | |||
| 113 | int node = spu->node; | 198 | int node = spu->node; |
| 114 | 199 | ||
| 115 | mutex_lock(&spu_prio->active_mutex[node]); | 200 | mutex_lock(&spu_prio->active_mutex[node]); |
| 116 | list_del_init(&spu->list); | 201 | __spu_remove_from_active_list(spu); |
| 117 | mutex_unlock(&spu_prio->active_mutex[node]); | 202 | mutex_unlock(&spu_prio->active_mutex[node]); |
| 118 | } | 203 | } |
| 119 | 204 | ||
| @@ -144,6 +229,10 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
| 144 | { | 229 | { |
| 145 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, | 230 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, |
| 146 | spu->number, spu->node); | 231 | spu->number, spu->node); |
| 232 | |||
| 233 | ctx->stats.slb_flt_base = spu->stats.slb_flt; | ||
| 234 | ctx->stats.class2_intr_base = spu->stats.class2_intr; | ||
| 235 | |||
| 147 | spu->ctx = ctx; | 236 | spu->ctx = ctx; |
| 148 | spu->flags = 0; | 237 | spu->flags = 0; |
| 149 | ctx->spu = spu; | 238 | ctx->spu = spu; |
| @@ -161,8 +250,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
| 161 | spu->timestamp = jiffies; | 250 | spu->timestamp = jiffies; |
| 162 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); | 251 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); |
| 163 | spu_switch_notify(spu, ctx); | 252 | spu_switch_notify(spu, ctx); |
| 164 | spu_add_to_active_list(spu); | ||
| 165 | ctx->state = SPU_STATE_RUNNABLE; | 253 | ctx->state = SPU_STATE_RUNNABLE; |
| 254 | spu_switch_state(spu, SPU_UTIL_SYSTEM); | ||
| 166 | } | 255 | } |
| 167 | 256 | ||
| 168 | /** | 257 | /** |
| @@ -175,7 +264,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
| 175 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, | 264 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, |
| 176 | spu->pid, spu->number, spu->node); | 265 | spu->pid, spu->number, spu->node); |
| 177 | 266 | ||
| 178 | spu_remove_from_active_list(spu); | 267 | spu_switch_state(spu, SPU_UTIL_IDLE); |
| 268 | |||
| 179 | spu_switch_notify(spu, NULL); | 269 | spu_switch_notify(spu, NULL); |
| 180 | spu_unmap_mappings(ctx); | 270 | spu_unmap_mappings(ctx); |
| 181 | spu_save(&ctx->csa, spu); | 271 | spu_save(&ctx->csa, spu); |
| @@ -192,6 +282,11 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
| 192 | ctx->spu = NULL; | 282 | ctx->spu = NULL; |
| 193 | spu->flags = 0; | 283 | spu->flags = 0; |
| 194 | spu->ctx = NULL; | 284 | spu->ctx = NULL; |
| 285 | |||
| 286 | ctx->stats.slb_flt += | ||
| 287 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); | ||
| 288 | ctx->stats.class2_intr += | ||
| 289 | (spu->stats.class2_intr - ctx->stats.class2_intr_base); | ||
| 195 | } | 290 | } |
| 196 | 291 | ||
| 197 | /** | 292 | /** |
| @@ -200,20 +295,39 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
| 200 | */ | 295 | */ |
| 201 | static void __spu_add_to_rq(struct spu_context *ctx) | 296 | static void __spu_add_to_rq(struct spu_context *ctx) |
| 202 | { | 297 | { |
| 203 | int prio = ctx->prio; | 298 | /* |
| 204 | 299 | * Unfortunately this code path can be called from multiple threads | |
| 205 | list_add_tail(&ctx->rq, &spu_prio->runq[prio]); | 300 | * on behalf of a single context due to the way the problem state |
| 206 | set_bit(prio, spu_prio->bitmap); | 301 | * mmap support works. |
| 302 | * | ||
| 303 | * Fortunately we need to wake up all these threads at the same time | ||
| 304 | * and can simply skip the runqueue addition for every but the first | ||
| 305 | * thread getting into this codepath. | ||
| 306 | * | ||
| 307 | * It's still quite hacky, and long-term we should proxy all other | ||
| 308 | * threads through the owner thread so that spu_run is in control | ||
| 309 | * of all the scheduling activity for a given context. | ||
| 310 | */ | ||
| 311 | if (list_empty(&ctx->rq)) { | ||
| 312 | list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); | ||
| 313 | set_bit(ctx->prio, spu_prio->bitmap); | ||
| 314 | if (!spu_prio->nr_waiting++) | ||
| 315 | __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); | ||
| 316 | } | ||
| 207 | } | 317 | } |
| 208 | 318 | ||
| 209 | static void __spu_del_from_rq(struct spu_context *ctx) | 319 | static void __spu_del_from_rq(struct spu_context *ctx) |
| 210 | { | 320 | { |
| 211 | int prio = ctx->prio; | 321 | int prio = ctx->prio; |
| 212 | 322 | ||
| 213 | if (!list_empty(&ctx->rq)) | 323 | if (!list_empty(&ctx->rq)) { |
| 324 | if (!--spu_prio->nr_waiting) | ||
| 325 | del_timer(&spusched_timer); | ||
| 214 | list_del_init(&ctx->rq); | 326 | list_del_init(&ctx->rq); |
| 215 | if (list_empty(&spu_prio->runq[prio])) | 327 | |
| 216 | clear_bit(prio, spu_prio->bitmap); | 328 | if (list_empty(&spu_prio->runq[prio])) |
| 329 | clear_bit(prio, spu_prio->bitmap); | ||
| 330 | } | ||
| 217 | } | 331 | } |
| 218 | 332 | ||
| 219 | static void spu_prio_wait(struct spu_context *ctx) | 333 | static void spu_prio_wait(struct spu_context *ctx) |
| @@ -244,7 +358,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
| 244 | 358 | ||
| 245 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 359 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
| 246 | node = (node < MAX_NUMNODES) ? node : 0; | 360 | node = (node < MAX_NUMNODES) ? node : 0; |
| 247 | if (!node_allowed(node)) | 361 | if (!node_allowed(ctx, node)) |
| 248 | continue; | 362 | continue; |
| 249 | spu = spu_alloc_node(node); | 363 | spu = spu_alloc_node(node); |
| 250 | if (spu) | 364 | if (spu) |
| @@ -276,15 +390,15 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
| 276 | node = cpu_to_node(raw_smp_processor_id()); | 390 | node = cpu_to_node(raw_smp_processor_id()); |
| 277 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 391 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
| 278 | node = (node < MAX_NUMNODES) ? node : 0; | 392 | node = (node < MAX_NUMNODES) ? node : 0; |
| 279 | if (!node_allowed(node)) | 393 | if (!node_allowed(ctx, node)) |
| 280 | continue; | 394 | continue; |
| 281 | 395 | ||
| 282 | mutex_lock(&spu_prio->active_mutex[node]); | 396 | mutex_lock(&spu_prio->active_mutex[node]); |
| 283 | list_for_each_entry(spu, &spu_prio->active_list[node], list) { | 397 | list_for_each_entry(spu, &spu_prio->active_list[node], list) { |
| 284 | struct spu_context *tmp = spu->ctx; | 398 | struct spu_context *tmp = spu->ctx; |
| 285 | 399 | ||
| 286 | if (tmp->rt_priority < ctx->rt_priority && | 400 | if (tmp->prio > ctx->prio && |
| 287 | (!victim || tmp->rt_priority < victim->rt_priority)) | 401 | (!victim || tmp->prio > victim->prio)) |
| 288 | victim = spu->ctx; | 402 | victim = spu->ctx; |
| 289 | } | 403 | } |
| 290 | mutex_unlock(&spu_prio->active_mutex[node]); | 404 | mutex_unlock(&spu_prio->active_mutex[node]); |
| @@ -312,7 +426,10 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
| 312 | victim = NULL; | 426 | victim = NULL; |
| 313 | goto restart; | 427 | goto restart; |
| 314 | } | 428 | } |
| 429 | spu_remove_from_active_list(spu); | ||
| 315 | spu_unbind_context(spu, victim); | 430 | spu_unbind_context(spu, victim); |
| 431 | victim->stats.invol_ctx_switch++; | ||
| 432 | spu->stats.invol_ctx_switch++; | ||
| 316 | mutex_unlock(&victim->state_mutex); | 433 | mutex_unlock(&victim->state_mutex); |
| 317 | /* | 434 | /* |
| 318 | * We need to break out of the wait loop in spu_run | 435 | * We need to break out of the wait loop in spu_run |
| @@ -338,22 +455,30 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
| 338 | */ | 455 | */ |
| 339 | int spu_activate(struct spu_context *ctx, unsigned long flags) | 456 | int spu_activate(struct spu_context *ctx, unsigned long flags) |
| 340 | { | 457 | { |
| 341 | 458 | spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); | |
| 342 | if (ctx->spu) | ||
| 343 | return 0; | ||
| 344 | 459 | ||
| 345 | do { | 460 | do { |
| 346 | struct spu *spu; | 461 | struct spu *spu; |
| 347 | 462 | ||
| 463 | /* | ||
| 464 | * If there are multiple threads waiting for a single context | ||
| 465 | * only one actually binds the context while the others will | ||
| 466 | * only be able to acquire the state_mutex once the context | ||
| 467 | * already is in runnable state. | ||
| 468 | */ | ||
| 469 | if (ctx->spu) | ||
| 470 | return 0; | ||
| 471 | |||
| 348 | spu = spu_get_idle(ctx); | 472 | spu = spu_get_idle(ctx); |
| 349 | /* | 473 | /* |
| 350 | * If this is a realtime thread we try to get it running by | 474 | * If this is a realtime thread we try to get it running by |
| 351 | * preempting a lower priority thread. | 475 | * preempting a lower priority thread. |
| 352 | */ | 476 | */ |
| 353 | if (!spu && ctx->rt_priority) | 477 | if (!spu && rt_prio(ctx->prio)) |
| 354 | spu = find_victim(ctx); | 478 | spu = find_victim(ctx); |
| 355 | if (spu) { | 479 | if (spu) { |
| 356 | spu_bind_context(spu, ctx); | 480 | spu_bind_context(spu, ctx); |
| 481 | spu_add_to_active_list(spu); | ||
| 357 | return 0; | 482 | return 0; |
| 358 | } | 483 | } |
| 359 | 484 | ||
| @@ -369,23 +494,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) | |||
| 369 | * Remove the highest priority context on the runqueue and return it | 494 | * Remove the highest priority context on the runqueue and return it |
| 370 | * to the caller. Returns %NULL if no runnable context was found. | 495 | * to the caller. Returns %NULL if no runnable context was found. |
| 371 | */ | 496 | */ |
| 372 | static struct spu_context *grab_runnable_context(int prio) | 497 | static struct spu_context *grab_runnable_context(int prio, int node) |
| 373 | { | 498 | { |
| 374 | struct spu_context *ctx = NULL; | 499 | struct spu_context *ctx; |
| 375 | int best; | 500 | int best; |
| 376 | 501 | ||
| 377 | spin_lock(&spu_prio->runq_lock); | 502 | spin_lock(&spu_prio->runq_lock); |
| 378 | best = sched_find_first_bit(spu_prio->bitmap); | 503 | best = sched_find_first_bit(spu_prio->bitmap); |
| 379 | if (best < prio) { | 504 | while (best < prio) { |
| 380 | struct list_head *rq = &spu_prio->runq[best]; | 505 | struct list_head *rq = &spu_prio->runq[best]; |
| 381 | 506 | ||
| 382 | BUG_ON(list_empty(rq)); | 507 | list_for_each_entry(ctx, rq, rq) { |
| 383 | 508 | /* XXX(hch): check for affinity here aswell */ | |
| 384 | ctx = list_entry(rq->next, struct spu_context, rq); | 509 | if (__node_allowed(ctx, node)) { |
| 385 | __spu_del_from_rq(ctx); | 510 | __spu_del_from_rq(ctx); |
| 511 | goto found; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | best++; | ||
| 386 | } | 515 | } |
| 516 | ctx = NULL; | ||
| 517 | found: | ||
| 387 | spin_unlock(&spu_prio->runq_lock); | 518 | spin_unlock(&spu_prio->runq_lock); |
| 388 | |||
| 389 | return ctx; | 519 | return ctx; |
| 390 | } | 520 | } |
| 391 | 521 | ||
| @@ -395,9 +525,12 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
| 395 | struct spu_context *new = NULL; | 525 | struct spu_context *new = NULL; |
| 396 | 526 | ||
| 397 | if (spu) { | 527 | if (spu) { |
| 398 | new = grab_runnable_context(max_prio); | 528 | new = grab_runnable_context(max_prio, spu->node); |
| 399 | if (new || force) { | 529 | if (new || force) { |
| 530 | spu_remove_from_active_list(spu); | ||
| 400 | spu_unbind_context(spu, ctx); | 531 | spu_unbind_context(spu, ctx); |
| 532 | ctx->stats.vol_ctx_switch++; | ||
| 533 | spu->stats.vol_ctx_switch++; | ||
| 401 | spu_free(spu); | 534 | spu_free(spu); |
| 402 | if (new) | 535 | if (new) |
| 403 | wake_up(&new->stop_wq); | 536 | wake_up(&new->stop_wq); |
| @@ -417,7 +550,17 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
| 417 | */ | 550 | */ |
| 418 | void spu_deactivate(struct spu_context *ctx) | 551 | void spu_deactivate(struct spu_context *ctx) |
| 419 | { | 552 | { |
| 553 | /* | ||
| 554 | * We must never reach this for a nosched context, | ||
| 555 | * but handle the case gracefull instead of panicing. | ||
| 556 | */ | ||
| 557 | if (ctx->flags & SPU_CREATE_NOSCHED) { | ||
| 558 | WARN_ON(1); | ||
| 559 | return; | ||
| 560 | } | ||
| 561 | |||
| 420 | __spu_deactivate(ctx, 1, MAX_PRIO); | 562 | __spu_deactivate(ctx, 1, MAX_PRIO); |
| 563 | spuctx_switch_state(ctx, SPUCTX_UTIL_USER); | ||
| 421 | } | 564 | } |
| 422 | 565 | ||
| 423 | /** | 566 | /** |
| @@ -432,56 +575,178 @@ void spu_yield(struct spu_context *ctx) | |||
| 432 | { | 575 | { |
| 433 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { | 576 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { |
| 434 | mutex_lock(&ctx->state_mutex); | 577 | mutex_lock(&ctx->state_mutex); |
| 435 | __spu_deactivate(ctx, 0, MAX_PRIO); | 578 | if (__spu_deactivate(ctx, 0, MAX_PRIO)) |
| 579 | spuctx_switch_state(ctx, SPUCTX_UTIL_USER); | ||
| 580 | else { | ||
| 581 | spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED); | ||
| 582 | spu_switch_state(ctx->spu, SPU_UTIL_USER); | ||
| 583 | } | ||
| 436 | mutex_unlock(&ctx->state_mutex); | 584 | mutex_unlock(&ctx->state_mutex); |
| 437 | } | 585 | } |
| 438 | } | 586 | } |
| 439 | 587 | ||
| 440 | void spu_sched_tick(struct work_struct *work) | 588 | static void spusched_tick(struct spu_context *ctx) |
| 441 | { | 589 | { |
| 442 | struct spu_context *ctx = | 590 | if (ctx->flags & SPU_CREATE_NOSCHED) |
| 443 | container_of(work, struct spu_context, sched_work.work); | 591 | return; |
| 444 | int preempted; | 592 | if (ctx->policy == SCHED_FIFO) |
| 593 | return; | ||
| 594 | |||
| 595 | if (--ctx->time_slice) | ||
| 596 | return; | ||
| 445 | 597 | ||
| 446 | /* | 598 | /* |
| 447 | * If this context is being stopped avoid rescheduling from the | 599 | * Unfortunately active_mutex ranks outside of state_mutex, so |
| 448 | * scheduler tick because we would block on the state_mutex. | 600 | * we have to trylock here. If we fail give the context another |
| 449 | * The caller will yield the spu later on anyway. | 601 | * tick and try again. |
| 450 | */ | 602 | */ |
| 451 | if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) | 603 | if (mutex_trylock(&ctx->state_mutex)) { |
| 452 | return; | 604 | struct spu *spu = ctx->spu; |
| 605 | struct spu_context *new; | ||
| 453 | 606 | ||
| 454 | mutex_lock(&ctx->state_mutex); | 607 | new = grab_runnable_context(ctx->prio + 1, spu->node); |
| 455 | preempted = __spu_deactivate(ctx, 0, ctx->prio + 1); | 608 | if (new) { |
| 456 | mutex_unlock(&ctx->state_mutex); | ||
| 457 | 609 | ||
| 458 | if (preempted) { | 610 | __spu_remove_from_active_list(spu); |
| 459 | /* | 611 | spu_unbind_context(spu, ctx); |
| 460 | * We need to break out of the wait loop in spu_run manually | 612 | ctx->stats.invol_ctx_switch++; |
| 461 | * to ensure this context gets put on the runqueue again | 613 | spu->stats.invol_ctx_switch++; |
| 462 | * ASAP. | 614 | spu_free(spu); |
| 463 | */ | 615 | wake_up(&new->stop_wq); |
| 464 | wake_up(&ctx->stop_wq); | 616 | /* |
| 617 | * We need to break out of the wait loop in | ||
| 618 | * spu_run manually to ensure this context | ||
| 619 | * gets put on the runqueue again ASAP. | ||
| 620 | */ | ||
| 621 | wake_up(&ctx->stop_wq); | ||
| 622 | } | ||
| 623 | spu_set_timeslice(ctx); | ||
| 624 | mutex_unlock(&ctx->state_mutex); | ||
| 465 | } else { | 625 | } else { |
| 466 | spu_start_tick(ctx); | 626 | ctx->time_slice++; |
| 467 | } | 627 | } |
| 468 | } | 628 | } |
| 469 | 629 | ||
| 470 | int __init spu_sched_init(void) | 630 | /** |
| 631 | * count_active_contexts - count nr of active tasks | ||
| 632 | * | ||
| 633 | * Return the number of tasks currently running or waiting to run. | ||
| 634 | * | ||
| 635 | * Note that we don't take runq_lock / active_mutex here. Reading | ||
| 636 | * a single 32bit value is atomic on powerpc, and we don't care | ||
| 637 | * about memory ordering issues here. | ||
| 638 | */ | ||
| 639 | static unsigned long count_active_contexts(void) | ||
| 471 | { | 640 | { |
| 472 | int i; | 641 | int nr_active = 0, node; |
| 473 | 642 | ||
| 474 | spu_sched_wq = create_singlethread_workqueue("spusched"); | 643 | for (node = 0; node < MAX_NUMNODES; node++) |
| 475 | if (!spu_sched_wq) | 644 | nr_active += spu_prio->nr_active[node]; |
| 476 | return 1; | 645 | nr_active += spu_prio->nr_waiting; |
| 477 | 646 | ||
| 478 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); | 647 | return nr_active; |
| 479 | if (!spu_prio) { | 648 | } |
| 480 | printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", | 649 | |
| 481 | __FUNCTION__); | 650 | /** |
| 482 | destroy_workqueue(spu_sched_wq); | 651 | * spu_calc_load - given tick count, update the avenrun load estimates. |
| 483 | return 1; | 652 | * @tick: tick count |
| 653 | * | ||
| 654 | * No locking against reading these values from userspace, as for | ||
| 655 | * the CPU loadavg code. | ||
| 656 | */ | ||
| 657 | static void spu_calc_load(unsigned long ticks) | ||
| 658 | { | ||
| 659 | unsigned long active_tasks; /* fixed-point */ | ||
| 660 | static int count = LOAD_FREQ; | ||
| 661 | |||
| 662 | count -= ticks; | ||
| 663 | |||
| 664 | if (unlikely(count < 0)) { | ||
| 665 | active_tasks = count_active_contexts() * FIXED_1; | ||
| 666 | do { | ||
| 667 | CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks); | ||
| 668 | CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks); | ||
| 669 | CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks); | ||
| 670 | count += LOAD_FREQ; | ||
| 671 | } while (count < 0); | ||
| 484 | } | 672 | } |
| 673 | } | ||
| 674 | |||
| 675 | static void spusched_wake(unsigned long data) | ||
| 676 | { | ||
| 677 | mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); | ||
| 678 | wake_up_process(spusched_task); | ||
| 679 | spu_calc_load(SPUSCHED_TICK); | ||
| 680 | } | ||
| 681 | |||
| 682 | static int spusched_thread(void *unused) | ||
| 683 | { | ||
| 684 | struct spu *spu, *next; | ||
| 685 | int node; | ||
| 686 | |||
| 687 | while (!kthread_should_stop()) { | ||
| 688 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 689 | schedule(); | ||
| 690 | for (node = 0; node < MAX_NUMNODES; node++) { | ||
| 691 | mutex_lock(&spu_prio->active_mutex[node]); | ||
| 692 | list_for_each_entry_safe(spu, next, | ||
| 693 | &spu_prio->active_list[node], | ||
| 694 | list) | ||
| 695 | spusched_tick(spu->ctx); | ||
| 696 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | #define LOAD_INT(x) ((x) >> FSHIFT) | ||
| 704 | #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) | ||
| 705 | |||
| 706 | static int show_spu_loadavg(struct seq_file *s, void *private) | ||
| 707 | { | ||
| 708 | int a, b, c; | ||
| 709 | |||
| 710 | a = spu_avenrun[0] + (FIXED_1/200); | ||
| 711 | b = spu_avenrun[1] + (FIXED_1/200); | ||
| 712 | c = spu_avenrun[2] + (FIXED_1/200); | ||
| 713 | |||
| 714 | /* | ||
| 715 | * Note that last_pid doesn't really make much sense for the | ||
| 716 | * SPU loadavg (it even seems very odd on the CPU side..), | ||
| 717 | * but we include it here to have a 100% compatible interface. | ||
| 718 | */ | ||
| 719 | seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n", | ||
| 720 | LOAD_INT(a), LOAD_FRAC(a), | ||
| 721 | LOAD_INT(b), LOAD_FRAC(b), | ||
| 722 | LOAD_INT(c), LOAD_FRAC(c), | ||
| 723 | count_active_contexts(), | ||
| 724 | atomic_read(&nr_spu_contexts), | ||
| 725 | current->nsproxy->pid_ns->last_pid); | ||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | |||
| 729 | static int spu_loadavg_open(struct inode *inode, struct file *file) | ||
| 730 | { | ||
| 731 | return single_open(file, show_spu_loadavg, NULL); | ||
| 732 | } | ||
| 733 | |||
| 734 | static const struct file_operations spu_loadavg_fops = { | ||
| 735 | .open = spu_loadavg_open, | ||
| 736 | .read = seq_read, | ||
| 737 | .llseek = seq_lseek, | ||
| 738 | .release = single_release, | ||
| 739 | }; | ||
| 740 | |||
| 741 | int __init spu_sched_init(void) | ||
| 742 | { | ||
| 743 | struct proc_dir_entry *entry; | ||
| 744 | int err = -ENOMEM, i; | ||
| 745 | |||
| 746 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); | ||
| 747 | if (!spu_prio) | ||
| 748 | goto out; | ||
| 749 | |||
| 485 | for (i = 0; i < MAX_PRIO; i++) { | 750 | for (i = 0; i < MAX_PRIO; i++) { |
| 486 | INIT_LIST_HEAD(&spu_prio->runq[i]); | 751 | INIT_LIST_HEAD(&spu_prio->runq[i]); |
| 487 | __clear_bit(i, spu_prio->bitmap); | 752 | __clear_bit(i, spu_prio->bitmap); |
| @@ -492,7 +757,30 @@ int __init spu_sched_init(void) | |||
| 492 | INIT_LIST_HEAD(&spu_prio->active_list[i]); | 757 | INIT_LIST_HEAD(&spu_prio->active_list[i]); |
| 493 | } | 758 | } |
| 494 | spin_lock_init(&spu_prio->runq_lock); | 759 | spin_lock_init(&spu_prio->runq_lock); |
| 760 | |||
| 761 | setup_timer(&spusched_timer, spusched_wake, 0); | ||
| 762 | |||
| 763 | spusched_task = kthread_run(spusched_thread, NULL, "spusched"); | ||
| 764 | if (IS_ERR(spusched_task)) { | ||
| 765 | err = PTR_ERR(spusched_task); | ||
| 766 | goto out_free_spu_prio; | ||
| 767 | } | ||
| 768 | |||
| 769 | entry = create_proc_entry("spu_loadavg", 0, NULL); | ||
| 770 | if (!entry) | ||
| 771 | goto out_stop_kthread; | ||
| 772 | entry->proc_fops = &spu_loadavg_fops; | ||
| 773 | |||
| 774 | pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n", | ||
| 775 | SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE); | ||
| 495 | return 0; | 776 | return 0; |
| 777 | |||
| 778 | out_stop_kthread: | ||
| 779 | kthread_stop(spusched_task); | ||
| 780 | out_free_spu_prio: | ||
| 781 | kfree(spu_prio); | ||
| 782 | out: | ||
| 783 | return err; | ||
| 496 | } | 784 | } |
| 497 | 785 | ||
| 498 | void __exit spu_sched_exit(void) | 786 | void __exit spu_sched_exit(void) |
| @@ -500,6 +788,11 @@ void __exit spu_sched_exit(void) | |||
| 500 | struct spu *spu, *tmp; | 788 | struct spu *spu, *tmp; |
| 501 | int node; | 789 | int node; |
| 502 | 790 | ||
| 791 | remove_proc_entry("spu_loadavg", NULL); | ||
| 792 | |||
| 793 | del_timer_sync(&spusched_timer); | ||
| 794 | kthread_stop(spusched_task); | ||
| 795 | |||
| 503 | for (node = 0; node < MAX_NUMNODES; node++) { | 796 | for (node = 0; node < MAX_NUMNODES; node++) { |
| 504 | mutex_lock(&spu_prio->active_mutex[node]); | 797 | mutex_lock(&spu_prio->active_mutex[node]); |
| 505 | list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], | 798 | list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], |
| @@ -510,5 +803,4 @@ void __exit spu_sched_exit(void) | |||
| 510 | mutex_unlock(&spu_prio->active_mutex[node]); | 803 | mutex_unlock(&spu_prio->active_mutex[node]); |
| 511 | } | 804 | } |
| 512 | kfree(spu_prio); | 805 | kfree(spu_prio); |
| 513 | destroy_workqueue(spu_sched_wq); | ||
| 514 | } | 806 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c index 0bf723dcd677..4e19ed7a0756 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore.c +++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c | |||
| @@ -296,7 +296,7 @@ static inline void restore_complete(void) | |||
| 296 | * This code deviates from the documented sequence in the | 296 | * This code deviates from the documented sequence in the |
| 297 | * following aspects: | 297 | * following aspects: |
| 298 | * | 298 | * |
| 299 | * 1. The EA for LSCSA is passed from PPE in the | 299 | * 1. The EA for LSCSA is passed from PPE in the |
| 300 | * signal notification channels. | 300 | * signal notification channels. |
| 301 | * 2. The register spill area is pulled by SPU | 301 | * 2. The register spill area is pulled by SPU |
| 302 | * into LS, rather than pushed by PPE. | 302 | * into LS, rather than pushed by PPE. |
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c index 196033b8a579..ae95cc1701e9 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_save.c +++ b/arch/powerpc/platforms/cell/spufs/spu_save.c | |||
| @@ -44,7 +44,7 @@ static inline void save_event_mask(void) | |||
| 44 | * Read the SPU_RdEventMsk channel and save to the LSCSA. | 44 | * Read the SPU_RdEventMsk channel and save to the LSCSA. |
| 45 | */ | 45 | */ |
| 46 | offset = LSCSA_QW_OFFSET(event_mask); | 46 | offset = LSCSA_QW_OFFSET(event_mask); |
| 47 | regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask); | 47 | regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static inline void save_tag_mask(void) | 50 | static inline void save_tag_mask(void) |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 47617e8014a5..08b3530288ac 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
| 27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
| 28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 29 | #include <linux/cpumask.h> | ||
| 29 | 30 | ||
| 30 | #include <asm/spu.h> | 31 | #include <asm/spu.h> |
| 31 | #include <asm/spu_csa.h> | 32 | #include <asm/spu_csa.h> |
| @@ -39,9 +40,17 @@ enum { | |||
| 39 | struct spu_context_ops; | 40 | struct spu_context_ops; |
| 40 | struct spu_gang; | 41 | struct spu_gang; |
| 41 | 42 | ||
| 42 | /* ctx->sched_flags */ | 43 | /* |
| 43 | enum { | 44 | * This is the state for spu utilization reporting to userspace. |
| 44 | SPU_SCHED_EXITING = 0, | 45 | * Because this state is visible to userspace it must never change and needs |
| 46 | * to be kept strictly separate from any internal state kept by the kernel. | ||
| 47 | */ | ||
| 48 | enum spuctx_execution_state { | ||
| 49 | SPUCTX_UTIL_USER = 0, | ||
| 50 | SPUCTX_UTIL_SYSTEM, | ||
| 51 | SPUCTX_UTIL_IOWAIT, | ||
| 52 | SPUCTX_UTIL_LOADED, | ||
| 53 | SPUCTX_UTIL_MAX | ||
| 45 | }; | 54 | }; |
| 46 | 55 | ||
| 47 | struct spu_context { | 56 | struct spu_context { |
| @@ -81,13 +90,34 @@ struct spu_context { | |||
| 81 | struct list_head gang_list; | 90 | struct list_head gang_list; |
| 82 | struct spu_gang *gang; | 91 | struct spu_gang *gang; |
| 83 | 92 | ||
| 93 | /* owner thread */ | ||
| 94 | pid_t tid; | ||
| 95 | |||
| 84 | /* scheduler fields */ | 96 | /* scheduler fields */ |
| 85 | struct list_head rq; | 97 | struct list_head rq; |
| 86 | struct delayed_work sched_work; | 98 | unsigned int time_slice; |
| 87 | unsigned long sched_flags; | 99 | unsigned long sched_flags; |
| 88 | unsigned long rt_priority; | 100 | cpumask_t cpus_allowed; |
| 89 | int policy; | 101 | int policy; |
| 90 | int prio; | 102 | int prio; |
| 103 | |||
| 104 | /* statistics */ | ||
| 105 | struct { | ||
| 106 | /* updates protected by ctx->state_mutex */ | ||
| 107 | enum spuctx_execution_state execution_state; | ||
| 108 | unsigned long tstamp; /* time of last ctx switch */ | ||
| 109 | unsigned long times[SPUCTX_UTIL_MAX]; | ||
| 110 | unsigned long long vol_ctx_switch; | ||
| 111 | unsigned long long invol_ctx_switch; | ||
| 112 | unsigned long long min_flt; | ||
| 113 | unsigned long long maj_flt; | ||
| 114 | unsigned long long hash_flt; | ||
| 115 | unsigned long long slb_flt; | ||
| 116 | unsigned long long slb_flt_base; /* # at last ctx switch */ | ||
| 117 | unsigned long long class2_intr; | ||
| 118 | unsigned long long class2_intr_base; /* # at last ctx switch */ | ||
| 119 | unsigned long long libassist; | ||
| 120 | } stats; | ||
| 91 | }; | 121 | }; |
| 92 | 122 | ||
| 93 | struct spu_gang { | 123 | struct spu_gang { |
| @@ -177,6 +207,7 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); | |||
| 177 | int spufs_handle_class1(struct spu_context *ctx); | 207 | int spufs_handle_class1(struct spu_context *ctx); |
| 178 | 208 | ||
| 179 | /* context management */ | 209 | /* context management */ |
| 210 | extern atomic_t nr_spu_contexts; | ||
| 180 | static inline void spu_acquire(struct spu_context *ctx) | 211 | static inline void spu_acquire(struct spu_context *ctx) |
| 181 | { | 212 | { |
| 182 | mutex_lock(&ctx->state_mutex); | 213 | mutex_lock(&ctx->state_mutex); |
| @@ -200,9 +231,9 @@ void spu_acquire_saved(struct spu_context *ctx); | |||
| 200 | int spu_activate(struct spu_context *ctx, unsigned long flags); | 231 | int spu_activate(struct spu_context *ctx, unsigned long flags); |
| 201 | void spu_deactivate(struct spu_context *ctx); | 232 | void spu_deactivate(struct spu_context *ctx); |
| 202 | void spu_yield(struct spu_context *ctx); | 233 | void spu_yield(struct spu_context *ctx); |
| 203 | void spu_start_tick(struct spu_context *ctx); | 234 | void spu_set_timeslice(struct spu_context *ctx); |
| 204 | void spu_stop_tick(struct spu_context *ctx); | 235 | void spu_update_sched_info(struct spu_context *ctx); |
| 205 | void spu_sched_tick(struct work_struct *work); | 236 | void __spu_update_sched_info(struct spu_context *ctx); |
| 206 | int __init spu_sched_init(void); | 237 | int __init spu_sched_init(void); |
| 207 | void __exit spu_sched_exit(void); | 238 | void __exit spu_sched_exit(void); |
| 208 | 239 | ||
| @@ -210,7 +241,7 @@ extern char *isolated_loader; | |||
| 210 | 241 | ||
| 211 | /* | 242 | /* |
| 212 | * spufs_wait | 243 | * spufs_wait |
| 213 | * Same as wait_event_interruptible(), except that here | 244 | * Same as wait_event_interruptible(), except that here |
| 214 | * we need to call spu_release(ctx) before sleeping, and | 245 | * we need to call spu_release(ctx) before sleeping, and |
| 215 | * then spu_acquire(ctx) when awoken. | 246 | * then spu_acquire(ctx) when awoken. |
| 216 | */ | 247 | */ |
| @@ -256,4 +287,37 @@ struct spufs_coredump_reader { | |||
| 256 | extern struct spufs_coredump_reader spufs_coredump_read[]; | 287 | extern struct spufs_coredump_reader spufs_coredump_read[]; |
| 257 | extern int spufs_coredump_num_notes; | 288 | extern int spufs_coredump_num_notes; |
| 258 | 289 | ||
| 290 | /* | ||
| 291 | * This function is a little bit too large for an inline, but | ||
| 292 | * as fault.c is built into the kernel we can't move it out of | ||
| 293 | * line. | ||
| 294 | */ | ||
| 295 | static inline void spuctx_switch_state(struct spu_context *ctx, | ||
| 296 | enum spuctx_execution_state new_state) | ||
| 297 | { | ||
| 298 | WARN_ON(!mutex_is_locked(&ctx->state_mutex)); | ||
| 299 | |||
| 300 | if (ctx->stats.execution_state != new_state) { | ||
| 301 | unsigned long curtime = jiffies; | ||
| 302 | |||
| 303 | ctx->stats.times[ctx->stats.execution_state] += | ||
| 304 | curtime - ctx->stats.tstamp; | ||
| 305 | ctx->stats.tstamp = curtime; | ||
| 306 | ctx->stats.execution_state = new_state; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | static inline void spu_switch_state(struct spu *spu, | ||
| 311 | enum spuctx_execution_state new_state) | ||
| 312 | { | ||
| 313 | if (spu->stats.utilization_state != new_state) { | ||
| 314 | unsigned long curtime = jiffies; | ||
| 315 | |||
| 316 | spu->stats.times[spu->stats.utilization_state] += | ||
| 317 | curtime - spu->stats.tstamp; | ||
| 318 | spu->stats.tstamp = curtime; | ||
| 319 | spu->stats.utilization_state = new_state; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 259 | #endif | 323 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 71a0b41adb8c..9c506ba08cdc 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
| @@ -70,7 +70,7 @@ | |||
| 70 | } | 70 | } |
| 71 | #endif /* debug */ | 71 | #endif /* debug */ |
| 72 | 72 | ||
| 73 | #define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) | 73 | #define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) |
| 74 | 74 | ||
| 75 | static inline void acquire_spu_lock(struct spu *spu) | 75 | static inline void acquire_spu_lock(struct spu *spu) |
| 76 | { | 76 | { |
| @@ -387,6 +387,19 @@ static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu) | |||
| 387 | csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW); | 387 | csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu) | ||
| 391 | { | ||
| 392 | struct spu_problem __iomem *prob = spu->problem; | ||
| 393 | |||
| 394 | /* Save the Prxy_TagStatus register in the CSA. | ||
| 395 | * | ||
| 396 | * It is unnecessary to restore dma_tagstatus_R, however, | ||
| 397 | * dma_tagstatus_R in the CSA is accessed via backing_ops, so | ||
| 398 | * we must save it. | ||
| 399 | */ | ||
| 400 | csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R); | ||
| 401 | } | ||
| 402 | |||
| 390 | static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu) | 403 | static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu) |
| 391 | { | 404 | { |
| 392 | struct spu_priv2 __iomem *priv2 = spu->priv2; | 405 | struct spu_priv2 __iomem *priv2 = spu->priv2; |
| @@ -1812,6 +1825,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu) | |||
| 1812 | save_mfc_queues(prev, spu); /* Step 19. */ | 1825 | save_mfc_queues(prev, spu); /* Step 19. */ |
| 1813 | save_ppu_querymask(prev, spu); /* Step 20. */ | 1826 | save_ppu_querymask(prev, spu); /* Step 20. */ |
| 1814 | save_ppu_querytype(prev, spu); /* Step 21. */ | 1827 | save_ppu_querytype(prev, spu); /* Step 21. */ |
| 1828 | save_ppu_tagstatus(prev, spu); /* NEW. */ | ||
| 1815 | save_mfc_csr_tsq(prev, spu); /* Step 22. */ | 1829 | save_mfc_csr_tsq(prev, spu); /* Step 22. */ |
| 1816 | save_mfc_csr_cmd(prev, spu); /* Step 23. */ | 1830 | save_mfc_csr_cmd(prev, spu); /* Step 23. */ |
| 1817 | save_mfc_csr_ato(prev, spu); /* Step 24. */ | 1831 | save_mfc_csr_ato(prev, spu); /* Step 24. */ |
| @@ -1930,7 +1944,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) | |||
| 1930 | reset_spu_privcntl(prev, spu); /* Step 16. */ | 1944 | reset_spu_privcntl(prev, spu); /* Step 16. */ |
| 1931 | reset_spu_lslr(prev, spu); /* Step 17. */ | 1945 | reset_spu_lslr(prev, spu); /* Step 17. */ |
| 1932 | setup_mfc_sr1(prev, spu); /* Step 18. */ | 1946 | setup_mfc_sr1(prev, spu); /* Step 18. */ |
| 1933 | spu_invalidate_slbs(spu); /* Step 19. */ | 1947 | spu_invalidate_slbs(spu); /* Step 19. */ |
| 1934 | reset_ch_part1(prev, spu); /* Step 20. */ | 1948 | reset_ch_part1(prev, spu); /* Step 20. */ |
| 1935 | reset_ch_part2(prev, spu); /* Step 21. */ | 1949 | reset_ch_part2(prev, spu); /* Step 21. */ |
| 1936 | enable_interrupts(prev, spu); /* Step 22. */ | 1950 | enable_interrupts(prev, spu); /* Step 22. */ |
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig index d2c690531963..22b4b4e3b6f0 100644 --- a/arch/powerpc/platforms/chrp/Kconfig +++ b/arch/powerpc/platforms/chrp/Kconfig | |||
| @@ -8,4 +8,5 @@ config PPC_CHRP | |||
| 8 | select PPC_MPC106 | 8 | select PPC_MPC106 |
| 9 | select PPC_UDBG_16550 | 9 | select PPC_UDBG_16550 |
| 10 | select PPC_NATIVE | 10 | select PPC_NATIVE |
| 11 | select PCI | ||
| 11 | default y | 12 | default y |
diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile index 902feb1ac431..4b3bfadc70fa 100644 --- a/arch/powerpc/platforms/chrp/Makefile +++ b/arch/powerpc/platforms/chrp/Makefile | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | obj-y += setup.o time.o pegasos_eth.o | 1 | obj-y += setup.o time.o pegasos_eth.o pci.o |
| 2 | obj-$(CONFIG_PCI) += pci.o | ||
| 3 | obj-$(CONFIG_SMP) += smp.o | 2 | obj-$(CONFIG_SMP) += smp.o |
| 4 | obj-$(CONFIG_NVRAM) += nvram.o | 3 | obj-$(CONFIG_NVRAM) += nvram.o |
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index d32fedc991d3..3690624e49d4 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
| @@ -99,7 +99,7 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 99 | struct pci_controller *hose = bus->sysdata; | 99 | struct pci_controller *hose = bus->sysdata; |
| 100 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 100 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 101 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 101 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
| 102 | | (hose->index << 24); | 102 | | (hose->global_number << 24); |
| 103 | int ret = -1; | 103 | int ret = -1; |
| 104 | int rval; | 104 | int rval; |
| 105 | 105 | ||
| @@ -114,7 +114,7 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 114 | struct pci_controller *hose = bus->sysdata; | 114 | struct pci_controller *hose = bus->sysdata; |
| 115 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 115 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 116 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 116 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
| 117 | | (hose->index << 24); | 117 | | (hose->global_number << 24); |
| 118 | int rval; | 118 | int rval; |
| 119 | 119 | ||
| 120 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | 120 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, |
| @@ -254,13 +254,12 @@ chrp_find_bridges(void) | |||
| 254 | printk(" at %llx", (unsigned long long)r.start); | 254 | printk(" at %llx", (unsigned long long)r.start); |
| 255 | printk("\n"); | 255 | printk("\n"); |
| 256 | 256 | ||
| 257 | hose = pcibios_alloc_controller(); | 257 | hose = pcibios_alloc_controller(dev); |
| 258 | if (!hose) { | 258 | if (!hose) { |
| 259 | printk("Can't allocate PCI controller structure for %s\n", | 259 | printk("Can't allocate PCI controller structure for %s\n", |
| 260 | dev->full_name); | 260 | dev->full_name); |
| 261 | continue; | 261 | continue; |
| 262 | } | 262 | } |
| 263 | hose->arch_data = dev; | ||
| 264 | hose->first_busno = bus_range[0]; | 263 | hose->first_busno = bus_range[0]; |
| 265 | hose->last_busno = bus_range[1]; | 264 | hose->last_busno = bus_range[1]; |
| 266 | 265 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index f2d26268ca6f..bec772674e40 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
| @@ -28,6 +28,7 @@ config PPC_HOLLY | |||
| 28 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" | 28 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" |
| 29 | select TSI108_BRIDGE | 29 | select TSI108_BRIDGE |
| 30 | select PPC_UDBG_16550 | 30 | select PPC_UDBG_16550 |
| 31 | select WANT_DEVICE_TREE | ||
| 31 | help | 32 | help |
| 32 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval | 33 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval |
| 33 | Board with TSI108/9 bridge (Hickory/Holly) | 34 | Board with TSI108/9 bridge (Hickory/Holly) |
| @@ -44,6 +45,7 @@ endchoice | |||
| 44 | config TSI108_BRIDGE | 45 | config TSI108_BRIDGE |
| 45 | bool | 46 | bool |
| 46 | depends on MPC7448HPC2 || PPC_HOLLY | 47 | depends on MPC7448HPC2 || PPC_HOLLY |
| 48 | select PCI | ||
| 47 | select MPIC | 49 | select MPIC |
| 48 | select MPIC_WEIRD | 50 | select MPIC_WEIRD |
| 49 | default y | 51 | default y |
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 3a0b4a01401c..6292e36dc577 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | 45 | ||
| 46 | #define HOLLY_PCI_CFG_PHYS 0x7c000000 | 46 | #define HOLLY_PCI_CFG_PHYS 0x7c000000 |
| 47 | 47 | ||
| 48 | int holly_exclude_device(u_char bus, u_char devfn) | 48 | int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) |
| 49 | { | 49 | { |
| 50 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 50 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
| 51 | return PCIBIOS_DEVICE_NOT_FOUND; | 51 | return PCIBIOS_DEVICE_NOT_FOUND; |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index b412f006a9c5..f4d0a7a603f5 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
| @@ -54,8 +54,9 @@ static struct mtd_partition linkstation_physmap_partitions[] = { | |||
| 54 | }, | 54 | }, |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | static int __init add_bridge(struct device_node *dev) | 57 | static int __init linkstation_add_bridge(struct device_node *dev) |
| 58 | { | 58 | { |
| 59 | #ifdef CONFIG_PCI | ||
| 59 | int len; | 60 | int len; |
| 60 | struct pci_controller *hose; | 61 | struct pci_controller *hose; |
| 61 | const int *bus_range; | 62 | const int *bus_range; |
| @@ -67,18 +68,17 @@ static int __init add_bridge(struct device_node *dev) | |||
| 67 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 68 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
| 68 | " bus 0\n", dev->full_name); | 69 | " bus 0\n", dev->full_name); |
| 69 | 70 | ||
| 70 | hose = pcibios_alloc_controller(); | 71 | hose = pcibios_alloc_controller(dev); |
| 71 | if (hose == NULL) | 72 | if (hose == NULL) |
| 72 | return -ENOMEM; | 73 | return -ENOMEM; |
| 73 | hose->first_busno = bus_range ? bus_range[0] : 0; | 74 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 74 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 75 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 75 | hose->arch_data = dev; | ||
| 76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | 76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); |
| 77 | 77 | ||
| 78 | /* Interpret the "ranges" property */ | 78 | /* Interpret the "ranges" property */ |
| 79 | /* This also maps the I/O region and sets isa_io/mem_base */ | 79 | /* This also maps the I/O region and sets isa_io/mem_base */ |
| 80 | pci_process_bridge_OF_ranges(hose, dev, 1); | 80 | pci_process_bridge_OF_ranges(hose, dev, 1); |
| 81 | 81 | #endif | |
| 82 | return 0; | 82 | return 0; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| @@ -92,7 +92,7 @@ static void __init linkstation_setup_arch(void) | |||
| 92 | 92 | ||
| 93 | /* Lookup PCI host bridges */ | 93 | /* Lookup PCI host bridges */ |
| 94 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 94 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
| 95 | add_bridge(np); | 95 | linkstation_add_bridge(np); |
| 96 | 96 | ||
| 97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); | 97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); |
| 98 | printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); | 98 | printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 4542e0c837c0..1e3cc69487b5 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | |||
| @@ -54,15 +54,10 @@ | |||
| 54 | 54 | ||
| 55 | #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 | 55 | #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 |
| 56 | 56 | ||
| 57 | #ifndef CONFIG_PCI | ||
| 58 | isa_io_base = MPC7448_HPC2_ISA_IO_BASE; | ||
| 59 | isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; | ||
| 60 | pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; | ||
| 61 | #endif | ||
| 62 | |||
| 63 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); | 57 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); |
| 64 | 58 | ||
| 65 | int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) | 59 | int mpc7448_hpc2_exclude_device(struct pci_controller *hose, |
| 60 | u_char bus, u_char devfn) | ||
| 66 | { | 61 | { |
| 67 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 62 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
| 68 | return PCIBIOS_DEVICE_NOT_FOUND; | 63 | return PCIBIOS_DEVICE_NOT_FOUND; |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h index a543a5242e34..f7e0e0c7f8d8 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h | |||
| @@ -18,9 +18,4 @@ | |||
| 18 | 18 | ||
| 19 | #include <asm/ppcboot.h> | 19 | #include <asm/ppcboot.h> |
| 20 | 20 | ||
| 21 | /* Base Addresses for the PCI bus | ||
| 22 | */ | ||
| 23 | #define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000) | ||
| 24 | #define MPC7448_HPC2_ISA_IO_BASE (0x00000000) | ||
| 25 | #define MPC7448_HPC2_ISA_MEM_BASE (0x00000000) | ||
| 26 | #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ | 21 | #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ |
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h index a843b0f87b72..8d95fe4b554e 100644 --- a/arch/powerpc/platforms/iseries/call_hpt.h +++ b/arch/powerpc/platforms/iseries/call_hpt.h | |||
| @@ -76,24 +76,25 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, | |||
| 76 | return compressedStatus; | 76 | return compressedStatus; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn) | 79 | static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn) |
| 80 | { | 80 | { |
| 81 | return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0); | 81 | return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex, | 84 | static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex, |
| 85 | u8 bitson, u8 bitsoff) | 85 | u8 bitson, u8 bitsoff) |
| 86 | { | 86 | { |
| 87 | return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex, | 87 | return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex, |
| 88 | bitson, bitsoff); | 88 | bitson, bitsoff); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex) | 91 | static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex) |
| 92 | { | 92 | { |
| 93 | HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0); | 93 | HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte) | 96 | static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, |
| 97 | struct hash_pte *hpte) | ||
| 97 | { | 98 | { |
| 98 | HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r); | 99 | HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r); |
| 99 | } | 100 | } |
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index ed44dfceaa45..b4e2c7a038e1 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c | |||
| @@ -44,7 +44,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 44 | unsigned long vflags, int psize) | 44 | unsigned long vflags, int psize) |
| 45 | { | 45 | { |
| 46 | long slot; | 46 | long slot; |
| 47 | hpte_t lhpte; | 47 | struct hash_pte lhpte; |
| 48 | int secondary = 0; | 48 | int secondary = 0; |
| 49 | 49 | ||
| 50 | BUG_ON(psize != MMU_PAGE_4K); | 50 | BUG_ON(psize != MMU_PAGE_4K); |
| @@ -99,7 +99,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 99 | 99 | ||
| 100 | static unsigned long iSeries_hpte_getword0(unsigned long slot) | 100 | static unsigned long iSeries_hpte_getword0(unsigned long slot) |
| 101 | { | 101 | { |
| 102 | hpte_t hpte; | 102 | struct hash_pte hpte; |
| 103 | 103 | ||
| 104 | HvCallHpt_get(&hpte, slot); | 104 | HvCallHpt_get(&hpte, slot); |
| 105 | return hpte.v; | 105 | return hpte.v; |
| @@ -144,7 +144,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group) | |||
| 144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | 144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, |
| 145 | unsigned long va, int psize, int local) | 145 | unsigned long va, int psize, int local) |
| 146 | { | 146 | { |
| 147 | hpte_t hpte; | 147 | struct hash_pte hpte; |
| 148 | unsigned long want_v; | 148 | unsigned long want_v; |
| 149 | 149 | ||
| 150 | iSeries_hlock(slot); | 150 | iSeries_hlock(slot); |
| @@ -176,7 +176,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 176 | */ | 176 | */ |
| 177 | static long iSeries_hpte_find(unsigned long vpn) | 177 | static long iSeries_hpte_find(unsigned long vpn) |
| 178 | { | 178 | { |
| 179 | hpte_t hpte; | 179 | struct hash_pte hpte; |
| 180 | long slot; | 180 | long slot; |
| 181 | 181 | ||
| 182 | /* | 182 | /* |
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 9c974227155e..da87162000f0 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
| @@ -742,6 +742,11 @@ void __init iSeries_pcibios_init(void) | |||
| 742 | /* Install IO hooks */ | 742 | /* Install IO hooks */ |
| 743 | ppc_pci_io = iseries_pci_io; | 743 | ppc_pci_io = iseries_pci_io; |
| 744 | 744 | ||
| 745 | /* iSeries has no IO space in the common sense, it needs to set | ||
| 746 | * the IO base to 0 | ||
| 747 | */ | ||
| 748 | pci_io_base = 0; | ||
| 749 | |||
| 745 | if (root == NULL) { | 750 | if (root == NULL) { |
| 746 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " | 751 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " |
| 747 | "of device tree\n"); | 752 | "of device tree\n"); |
| @@ -763,7 +768,7 @@ void __init iSeries_pcibios_init(void) | |||
| 763 | if (phb == NULL) | 768 | if (phb == NULL) |
| 764 | continue; | 769 | continue; |
| 765 | 770 | ||
| 766 | phb->pci_mem_offset = phb->local_number = bus; | 771 | phb->pci_mem_offset = bus; |
| 767 | phb->first_busno = bus; | 772 | phb->first_busno = bus; |
| 768 | phb->last_busno = bus; | 773 | phb->last_busno = bus; |
| 769 | phb->ops = &iSeries_pci_ops; | 774 | phb->ops = &iSeries_pci_ops; |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 7f5dcee814d4..13a8b1908ded 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
| @@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void); | |||
| 79 | static void iSeries_pci_final_fixup(void) { } | 79 | static void iSeries_pci_final_fixup(void) { } |
| 80 | #endif | 80 | #endif |
| 81 | 81 | ||
| 82 | extern unsigned long iSeries_recal_tb; | ||
| 83 | extern unsigned long iSeries_recal_titan; | ||
| 84 | 82 | ||
| 85 | struct MemoryBlock { | 83 | struct MemoryBlock { |
| 86 | unsigned long absStart; | 84 | unsigned long absStart; |
| @@ -292,8 +290,8 @@ static void __init iSeries_init_early(void) | |||
| 292 | { | 290 | { |
| 293 | DBG(" -> iSeries_init_early()\n"); | 291 | DBG(" -> iSeries_init_early()\n"); |
| 294 | 292 | ||
| 295 | iSeries_recal_tb = get_tb(); | 293 | /* Snapshot the timebase, for use in later recalibration */ |
| 296 | iSeries_recal_titan = HvCallXm_loadTod(); | 294 | iSeries_time_init_early(); |
| 297 | 295 | ||
| 298 | /* | 296 | /* |
| 299 | * Initialize the DMA/TCE management | 297 | * Initialize the DMA/TCE management |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 7aaa5bbc9363..fceaae40fe70 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
| @@ -444,7 +444,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
| 444 | u3_ht = hose; | 444 | u3_ht = hose; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static int __init add_bridge(struct device_node *dev) | 447 | static int __init maple_add_bridge(struct device_node *dev) |
| 448 | { | 448 | { |
| 449 | int len; | 449 | int len; |
| 450 | struct pci_controller *hose; | 450 | struct pci_controller *hose; |
| @@ -519,23 +519,6 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev) | |||
| 519 | DBG(" <- maple_pci_irq_fixup\n"); | 519 | DBG(" <- maple_pci_irq_fixup\n"); |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | static void __init maple_fixup_phb_resources(void) | ||
| 523 | { | ||
| 524 | struct pci_controller *hose, *tmp; | ||
| 525 | |||
| 526 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 527 | unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
| 528 | |||
| 529 | hose->io_resource.start += offset; | ||
| 530 | hose->io_resource.end += offset; | ||
| 531 | |||
| 532 | printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n", | ||
| 533 | hose->global_number, | ||
| 534 | (unsigned long long)hose->io_resource.start, | ||
| 535 | (unsigned long long)hose->io_resource.end); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | void __init maple_pci_init(void) | 522 | void __init maple_pci_init(void) |
| 540 | { | 523 | { |
| 541 | struct device_node *np, *root; | 524 | struct device_node *np, *root; |
| @@ -558,7 +541,7 @@ void __init maple_pci_init(void) | |||
| 558 | continue; | 541 | continue; |
| 559 | if ((of_device_is_compatible(np, "u4-pcie") || | 542 | if ((of_device_is_compatible(np, "u4-pcie") || |
| 560 | of_device_is_compatible(np, "u3-agp")) && | 543 | of_device_is_compatible(np, "u3-agp")) && |
| 561 | add_bridge(np) == 0) | 544 | maple_add_bridge(np) == 0) |
| 562 | of_node_get(np); | 545 | of_node_get(np); |
| 563 | 546 | ||
| 564 | if (of_device_is_compatible(np, "u3-ht")) { | 547 | if (of_device_is_compatible(np, "u3-ht")) { |
| @@ -570,27 +553,9 @@ void __init maple_pci_init(void) | |||
| 570 | 553 | ||
| 571 | /* Now setup the HyperTransport host if we found any | 554 | /* Now setup the HyperTransport host if we found any |
| 572 | */ | 555 | */ |
| 573 | if (ht && add_bridge(ht) != 0) | 556 | if (ht && maple_add_bridge(ht) != 0) |
| 574 | of_node_put(ht); | 557 | of_node_put(ht); |
| 575 | 558 | ||
| 576 | /* | ||
| 577 | * We need to call pci_setup_phb_io for the HT bridge first | ||
| 578 | * so it gets the I/O port numbers starting at 0, and we | ||
| 579 | * need to call it for the AGP bridge after that so it gets | ||
| 580 | * small positive I/O port numbers. | ||
| 581 | */ | ||
| 582 | if (u3_ht) | ||
| 583 | pci_setup_phb_io(u3_ht, 1); | ||
| 584 | if (u3_agp) | ||
| 585 | pci_setup_phb_io(u3_agp, 0); | ||
| 586 | if (u4_pcie) | ||
| 587 | pci_setup_phb_io(u4_pcie, 0); | ||
| 588 | |||
| 589 | /* Fixup the IO resources on our host bridges as the common code | ||
| 590 | * does it only for childs of the host bridges | ||
| 591 | */ | ||
| 592 | maple_fixup_phb_resources(); | ||
| 593 | |||
| 594 | /* Setup the linkage between OF nodes and PHBs */ | 559 | /* Setup the linkage between OF nodes and PHBs */ |
| 595 | pci_devs_phb_init(); | 560 | pci_devs_phb_init(); |
| 596 | 561 | ||
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index 7c5076e38ea1..95cd90fd81c7 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
| @@ -25,4 +25,13 @@ config PPC_PASEMI_MDIO | |||
| 25 | help | 25 | help |
| 26 | Driver for MDIO via GPIO on PWRficient platforms | 26 | Driver for MDIO via GPIO on PWRficient platforms |
| 27 | 27 | ||
| 28 | config ELECTRA_IDE | ||
| 29 | tristate "Electra IDE driver" | ||
| 30 | default y | ||
| 31 | depends on PPC_PASEMI && ATA | ||
| 32 | select PATA_PLATFORM | ||
| 33 | help | ||
| 34 | This includes driver support for the Electra on-board IDE | ||
| 35 | interface. | ||
| 36 | |||
| 28 | endmenu | 37 | endmenu |
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index 2cd2a4f26a48..f47fcac7e581 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o | 1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o |
| 2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o | 2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o |
| 3 | obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o | ||
| 3 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o | 4 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o |
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c new file mode 100644 index 000000000000..12fb0c949263 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/electra_ide.c | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007 PA Semi, Inc | ||
| 3 | * | ||
| 4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
| 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 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/platform_device.h> | ||
| 21 | |||
| 22 | #include <asm/prom.h> | ||
| 23 | #include <asm/system.h> | ||
| 24 | |||
| 25 | /* The electra IDE interface is incredibly simple: Just a device on the localbus | ||
| 26 | * with interrupts hooked up to one of the GPIOs. The device tree contains the | ||
| 27 | * address window and interrupt mappings already, and the pata_platform driver handles | ||
| 28 | * the rest. We just need to hook the two up. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define MAX_IFS 4 /* really, we have only one */ | ||
| 32 | |||
| 33 | static struct platform_device *pdevs[MAX_IFS]; | ||
| 34 | |||
| 35 | static int __devinit electra_ide_init(void) | ||
| 36 | { | ||
| 37 | struct device_node *np; | ||
| 38 | struct resource r[3]; | ||
| 39 | int ret = 0; | ||
| 40 | int i; | ||
| 41 | |||
| 42 | np = of_find_compatible_node(NULL, "ide", "electra-ide"); | ||
| 43 | i = 0; | ||
| 44 | |||
| 45 | while (np && i < MAX_IFS) { | ||
| 46 | memset(r, 0, sizeof(r)); | ||
| 47 | |||
| 48 | /* pata_platform wants two address ranges: one for the base registers, | ||
| 49 | * another for the control (altstatus). It's located at offset 0x3f6 in | ||
| 50 | * the window, but the device tree only has one large register window | ||
| 51 | * that covers both ranges. So we need to split it up by hand here: | ||
| 52 | */ | ||
| 53 | |||
| 54 | ret = of_address_to_resource(np, 0, &r[0]); | ||
| 55 | if (ret) | ||
| 56 | goto out; | ||
| 57 | ret = of_address_to_resource(np, 0, &r[1]); | ||
| 58 | if (ret) | ||
| 59 | goto out; | ||
| 60 | |||
| 61 | r[1].start += 0x3f6; | ||
| 62 | r[0].end = r[1].start-1; | ||
| 63 | |||
| 64 | r[2].start = irq_of_parse_and_map(np, 0); | ||
| 65 | r[2].end = irq_of_parse_and_map(np, 0); | ||
| 66 | r[2].flags = IORESOURCE_IRQ; | ||
| 67 | |||
| 68 | pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n", | ||
| 69 | r[0].start, r[1].start, r[2].start); | ||
| 70 | pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3); | ||
| 71 | if (IS_ERR(pdevs[i])) { | ||
| 72 | ret = PTR_ERR(pdevs[i]); | ||
| 73 | pdevs[i] = NULL; | ||
| 74 | goto out; | ||
| 75 | } | ||
| 76 | np = of_find_compatible_node(np, "ide", "electra-ide"); | ||
| 77 | } | ||
| 78 | out: | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | module_init(electra_ide_init); | ||
| 82 | |||
| 83 | static void __devexit electra_ide_exit(void) | ||
| 84 | { | ||
| 85 | int i; | ||
| 86 | |||
| 87 | for (i = 0; i < MAX_IFS; i++) | ||
| 88 | if (pdevs[i]) | ||
| 89 | platform_device_unregister(pdevs[i]); | ||
| 90 | } | ||
| 91 | module_exit(electra_ide_exit); | ||
| 92 | |||
| 93 | |||
| 94 | MODULE_LICENSE("GPL"); | ||
| 95 | MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); | ||
| 96 | MODULE_DESCRIPTION("PA Semi Electra IDE driver"); | ||
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index bbc6dfcfaa91..ab1f5f62bcd8 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
| @@ -132,7 +132,7 @@ static void __init setup_pa_pxp(struct pci_controller *hose) | |||
| 132 | hose->cfg_data = ioremap(0xe0000000, 0x10000000); | 132 | hose->cfg_data = ioremap(0xe0000000, 0x10000000); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | static int __init add_bridge(struct device_node *dev) | 135 | static int __init pas_add_bridge(struct device_node *dev) |
| 136 | { | 136 | { |
| 137 | struct pci_controller *hose; | 137 | struct pci_controller *hose; |
| 138 | 138 | ||
| @@ -150,29 +150,11 @@ static int __init add_bridge(struct device_node *dev) | |||
| 150 | printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); | 150 | printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); |
| 151 | 151 | ||
| 152 | /* Interpret the "ranges" property */ | 152 | /* Interpret the "ranges" property */ |
| 153 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
| 154 | pci_process_bridge_OF_ranges(hose, dev, 1); | 153 | pci_process_bridge_OF_ranges(hose, dev, 1); |
| 155 | pci_setup_phb_io(hose, 1); | ||
| 156 | 154 | ||
| 157 | return 0; | 155 | return 0; |
| 158 | } | 156 | } |
| 159 | 157 | ||
| 160 | |||
| 161 | static void __init pas_fixup_phb_resources(void) | ||
| 162 | { | ||
| 163 | struct pci_controller *hose, *tmp; | ||
| 164 | |||
| 165 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 166 | unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
| 167 | hose->io_resource.start += offset; | ||
| 168 | hose->io_resource.end += offset; | ||
| 169 | printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", | ||
| 170 | hose->global_number, | ||
| 171 | hose->io_resource.start, hose->io_resource.end); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 176 | void __init pas_pci_init(void) | 158 | void __init pas_pci_init(void) |
| 177 | { | 159 | { |
| 178 | struct device_node *np, *root; | 160 | struct device_node *np, *root; |
| @@ -185,13 +167,11 @@ void __init pas_pci_init(void) | |||
| 185 | } | 167 | } |
| 186 | 168 | ||
| 187 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) | 169 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) |
| 188 | if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np)) | 170 | if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) |
| 189 | of_node_get(np); | 171 | of_node_get(np); |
| 190 | 172 | ||
| 191 | of_node_put(root); | 173 | of_node_put(root); |
| 192 | 174 | ||
| 193 | pas_fixup_phb_resources(); | ||
| 194 | |||
| 195 | /* Setup the linkage between OF nodes and PHBs */ | 175 | /* Setup the linkage between OF nodes and PHBs */ |
| 196 | pci_devs_phb_init(); | 176 | pci_devs_phb_init(); |
| 197 | 177 | ||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index c5a3f61f8d85..ffe6528048b5 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
| @@ -239,7 +239,7 @@ static int __init pas_probe(void) | |||
| 239 | return 1; | 239 | return 1; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | define_machine(pas) { | 242 | define_machine(pasemi) { |
| 243 | .name = "PA Semi PA6T-1682M", | 243 | .name = "PA Semi PA6T-1682M", |
| 244 | .probe = pas_probe, | 244 | .probe = pas_probe, |
| 245 | .setup_arch = pas_setup_arch, | 245 | .setup_arch = pas_setup_arch, |
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 5b7afe50039a..055990ca8ce6 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig | |||
| @@ -2,6 +2,7 @@ config PPC_PMAC | |||
| 2 | bool "Apple PowerMac based machines" | 2 | bool "Apple PowerMac based machines" |
| 3 | depends on PPC_MULTIPLATFORM | 3 | depends on PPC_MULTIPLATFORM |
| 4 | select MPIC | 4 | select MPIC |
| 5 | select PCI | ||
| 5 | select PPC_INDIRECT_PCI if PPC32 | 6 | select PPC_INDIRECT_PCI if PPC32 |
| 6 | select PPC_MPC106 if PPC32 | 7 | select PPC_MPC106 if PPC32 |
| 7 | select PPC_NATIVE | 8 | select PPC_NATIVE |
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 3f507ab9c5e5..efdf5eb81ecc 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
| 43 | #include <linux/completion.h> | 43 | #include <linux/completion.h> |
| 44 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
| 45 | #include <linux/mutex.h> | ||
| 45 | #include <asm/keylargo.h> | 46 | #include <asm/keylargo.h> |
| 46 | #include <asm/uninorth.h> | 47 | #include <asm/uninorth.h> |
| 47 | #include <asm/io.h> | 48 | #include <asm/io.h> |
| @@ -84,7 +85,7 @@ struct pmac_i2c_bus | |||
| 84 | void *hostdata; | 85 | void *hostdata; |
| 85 | int channel; /* some hosts have multiple */ | 86 | int channel; /* some hosts have multiple */ |
| 86 | int mode; /* current mode */ | 87 | int mode; /* current mode */ |
| 87 | struct semaphore sem; | 88 | struct mutex mutex; |
| 88 | int opened; | 89 | int opened; |
| 89 | int polled; /* open mode */ | 90 | int polled; /* open mode */ |
| 90 | struct platform_device *platform_dev; | 91 | struct platform_device *platform_dev; |
| @@ -104,7 +105,7 @@ static LIST_HEAD(pmac_i2c_busses); | |||
| 104 | 105 | ||
| 105 | struct pmac_i2c_host_kw | 106 | struct pmac_i2c_host_kw |
| 106 | { | 107 | { |
| 107 | struct semaphore mutex; /* Access mutex for use by | 108 | struct mutex mutex; /* Access mutex for use by |
| 108 | * i2c-keywest */ | 109 | * i2c-keywest */ |
| 109 | void __iomem *base; /* register base address */ | 110 | void __iomem *base; /* register base address */ |
| 110 | int bsteps; /* register stepping */ | 111 | int bsteps; /* register stepping */ |
| @@ -375,14 +376,14 @@ static void kw_i2c_timeout(unsigned long data) | |||
| 375 | static int kw_i2c_open(struct pmac_i2c_bus *bus) | 376 | static int kw_i2c_open(struct pmac_i2c_bus *bus) |
| 376 | { | 377 | { |
| 377 | struct pmac_i2c_host_kw *host = bus->hostdata; | 378 | struct pmac_i2c_host_kw *host = bus->hostdata; |
| 378 | down(&host->mutex); | 379 | mutex_lock(&host->mutex); |
| 379 | return 0; | 380 | return 0; |
| 380 | } | 381 | } |
| 381 | 382 | ||
| 382 | static void kw_i2c_close(struct pmac_i2c_bus *bus) | 383 | static void kw_i2c_close(struct pmac_i2c_bus *bus) |
| 383 | { | 384 | { |
| 384 | struct pmac_i2c_host_kw *host = bus->hostdata; | 385 | struct pmac_i2c_host_kw *host = bus->hostdata; |
| 385 | up(&host->mutex); | 386 | mutex_unlock(&host->mutex); |
| 386 | } | 387 | } |
| 387 | 388 | ||
| 388 | static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | 389 | static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, |
| @@ -498,7 +499,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) | |||
| 498 | kfree(host); | 499 | kfree(host); |
| 499 | return NULL; | 500 | return NULL; |
| 500 | } | 501 | } |
| 501 | init_MUTEX(&host->mutex); | 502 | mutex_init(&host->mutex); |
| 502 | init_completion(&host->complete); | 503 | init_completion(&host->complete); |
| 503 | spin_lock_init(&host->lock); | 504 | spin_lock_init(&host->lock); |
| 504 | init_timer(&host->timeout_timer); | 505 | init_timer(&host->timeout_timer); |
| @@ -571,7 +572,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, | |||
| 571 | bus->open = kw_i2c_open; | 572 | bus->open = kw_i2c_open; |
| 572 | bus->close = kw_i2c_close; | 573 | bus->close = kw_i2c_close; |
| 573 | bus->xfer = kw_i2c_xfer; | 574 | bus->xfer = kw_i2c_xfer; |
| 574 | init_MUTEX(&bus->sem); | 575 | mutex_init(&bus->mutex); |
| 575 | if (controller == busnode) | 576 | if (controller == busnode) |
| 576 | bus->flags = pmac_i2c_multibus; | 577 | bus->flags = pmac_i2c_multibus; |
| 577 | list_add(&bus->link, &pmac_i2c_busses); | 578 | list_add(&bus->link, &pmac_i2c_busses); |
| @@ -798,7 +799,7 @@ static void __init pmu_i2c_probe(void) | |||
| 798 | bus->mode = pmac_i2c_mode_std; | 799 | bus->mode = pmac_i2c_mode_std; |
| 799 | bus->hostdata = bus + 1; | 800 | bus->hostdata = bus + 1; |
| 800 | bus->xfer = pmu_i2c_xfer; | 801 | bus->xfer = pmu_i2c_xfer; |
| 801 | init_MUTEX(&bus->sem); | 802 | mutex_init(&bus->mutex); |
| 802 | bus->flags = pmac_i2c_multibus; | 803 | bus->flags = pmac_i2c_multibus; |
| 803 | list_add(&bus->link, &pmac_i2c_busses); | 804 | list_add(&bus->link, &pmac_i2c_busses); |
| 804 | 805 | ||
| @@ -921,7 +922,7 @@ static void __init smu_i2c_probe(void) | |||
| 921 | bus->mode = pmac_i2c_mode_std; | 922 | bus->mode = pmac_i2c_mode_std; |
| 922 | bus->hostdata = bus + 1; | 923 | bus->hostdata = bus + 1; |
| 923 | bus->xfer = smu_i2c_xfer; | 924 | bus->xfer = smu_i2c_xfer; |
| 924 | init_MUTEX(&bus->sem); | 925 | mutex_init(&bus->mutex); |
| 925 | bus->flags = 0; | 926 | bus->flags = 0; |
| 926 | list_add(&bus->link, &pmac_i2c_busses); | 927 | list_add(&bus->link, &pmac_i2c_busses); |
| 927 | 928 | ||
| @@ -1093,13 +1094,13 @@ int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled) | |||
| 1093 | { | 1094 | { |
| 1094 | int rc; | 1095 | int rc; |
| 1095 | 1096 | ||
| 1096 | down(&bus->sem); | 1097 | mutex_lock(&bus->mutex); |
| 1097 | bus->polled = polled || pmac_i2c_force_poll; | 1098 | bus->polled = polled || pmac_i2c_force_poll; |
| 1098 | bus->opened = 1; | 1099 | bus->opened = 1; |
| 1099 | bus->mode = pmac_i2c_mode_std; | 1100 | bus->mode = pmac_i2c_mode_std; |
| 1100 | if (bus->open && (rc = bus->open(bus)) != 0) { | 1101 | if (bus->open && (rc = bus->open(bus)) != 0) { |
| 1101 | bus->opened = 0; | 1102 | bus->opened = 0; |
| 1102 | up(&bus->sem); | 1103 | mutex_unlock(&bus->mutex); |
| 1103 | return rc; | 1104 | return rc; |
| 1104 | } | 1105 | } |
| 1105 | return 0; | 1106 | return 0; |
| @@ -1112,7 +1113,7 @@ void pmac_i2c_close(struct pmac_i2c_bus *bus) | |||
| 1112 | if (bus->close) | 1113 | if (bus->close) |
| 1113 | bus->close(bus); | 1114 | bus->close(bus); |
| 1114 | bus->opened = 0; | 1115 | bus->opened = 0; |
| 1115 | up(&bus->sem); | 1116 | mutex_unlock(&bus->mutex); |
| 1116 | } | 1117 | } |
| 1117 | EXPORT_SYMBOL_GPL(pmac_i2c_close); | 1118 | EXPORT_SYMBOL_GPL(pmac_i2c_close); |
| 1118 | 1119 | ||
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index c4af9e21ac93..92586db19754 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
| @@ -35,8 +35,6 @@ | |||
| 35 | #define DBG(x...) | 35 | #define DBG(x...) |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | static int add_bridge(struct device_node *dev); | ||
| 39 | |||
| 40 | /* XXX Could be per-controller, but I don't think we risk anything by | 38 | /* XXX Could be per-controller, but I don't think we risk anything by |
| 41 | * assuming we won't have both UniNorth and Bandit */ | 39 | * assuming we won't have both UniNorth and Bandit */ |
| 42 | static int has_uninorth; | 40 | static int has_uninorth; |
| @@ -897,7 +895,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
| 897 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, | 895 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, |
| 898 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. | 896 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. |
| 899 | */ | 897 | */ |
| 900 | static int __init add_bridge(struct device_node *dev) | 898 | static int __init pmac_add_bridge(struct device_node *dev) |
| 901 | { | 899 | { |
| 902 | int len; | 900 | int len; |
| 903 | struct pci_controller *hose; | 901 | struct pci_controller *hose; |
| @@ -918,15 +916,9 @@ static int __init add_bridge(struct device_node *dev) | |||
| 918 | " bus 0\n", dev->full_name); | 916 | " bus 0\n", dev->full_name); |
| 919 | } | 917 | } |
| 920 | 918 | ||
| 921 | /* XXX Different prototypes, to be merged */ | ||
| 922 | #ifdef CONFIG_PPC64 | ||
| 923 | hose = pcibios_alloc_controller(dev); | 919 | hose = pcibios_alloc_controller(dev); |
| 924 | #else | ||
| 925 | hose = pcibios_alloc_controller(); | ||
| 926 | #endif | ||
| 927 | if (!hose) | 920 | if (!hose) |
| 928 | return -ENOMEM; | 921 | return -ENOMEM; |
| 929 | hose->arch_data = dev; | ||
| 930 | hose->first_busno = bus_range ? bus_range[0] : 0; | 922 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 931 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 923 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 932 | 924 | ||
| @@ -1006,19 +998,6 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev) | |||
| 1006 | #endif /* CONFIG_PPC32 */ | 998 | #endif /* CONFIG_PPC32 */ |
| 1007 | } | 999 | } |
| 1008 | 1000 | ||
| 1009 | #ifdef CONFIG_PPC64 | ||
| 1010 | static void __init pmac_fixup_phb_resources(void) | ||
| 1011 | { | ||
| 1012 | struct pci_controller *hose, *tmp; | ||
| 1013 | |||
| 1014 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 1015 | printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", | ||
| 1016 | hose->global_number, | ||
| 1017 | hose->io_resource.start, hose->io_resource.end); | ||
| 1018 | } | ||
| 1019 | } | ||
| 1020 | #endif | ||
| 1021 | |||
| 1022 | void __init pmac_pci_init(void) | 1001 | void __init pmac_pci_init(void) |
| 1023 | { | 1002 | { |
| 1024 | struct device_node *np, *root; | 1003 | struct device_node *np, *root; |
| @@ -1036,7 +1015,7 @@ void __init pmac_pci_init(void) | |||
| 1036 | if (strcmp(np->name, "bandit") == 0 | 1015 | if (strcmp(np->name, "bandit") == 0 |
| 1037 | || strcmp(np->name, "chaos") == 0 | 1016 | || strcmp(np->name, "chaos") == 0 |
| 1038 | || strcmp(np->name, "pci") == 0) { | 1017 | || strcmp(np->name, "pci") == 0) { |
| 1039 | if (add_bridge(np) == 0) | 1018 | if (pmac_add_bridge(np) == 0) |
| 1040 | of_node_get(np); | 1019 | of_node_get(np); |
| 1041 | } | 1020 | } |
| 1042 | if (strcmp(np->name, "ht") == 0) { | 1021 | if (strcmp(np->name, "ht") == 0) { |
| @@ -1050,28 +1029,9 @@ void __init pmac_pci_init(void) | |||
| 1050 | /* Probe HT last as it relies on the agp resources to be already | 1029 | /* Probe HT last as it relies on the agp resources to be already |
| 1051 | * setup | 1030 | * setup |
| 1052 | */ | 1031 | */ |
| 1053 | if (ht && add_bridge(ht) != 0) | 1032 | if (ht && pmac_add_bridge(ht) != 0) |
| 1054 | of_node_put(ht); | 1033 | of_node_put(ht); |
| 1055 | 1034 | ||
| 1056 | /* | ||
| 1057 | * We need to call pci_setup_phb_io for the HT bridge first | ||
| 1058 | * so it gets the I/O port numbers starting at 0, and we | ||
| 1059 | * need to call it for the AGP bridge after that so it gets | ||
| 1060 | * small positive I/O port numbers. | ||
| 1061 | */ | ||
| 1062 | if (u3_ht) | ||
| 1063 | pci_setup_phb_io(u3_ht, 1); | ||
| 1064 | if (u3_agp) | ||
| 1065 | pci_setup_phb_io(u3_agp, 0); | ||
| 1066 | if (u4_pcie) | ||
| 1067 | pci_setup_phb_io(u4_pcie, 0); | ||
| 1068 | |||
| 1069 | /* | ||
| 1070 | * On ppc64, fixup the IO resources on our host bridges as | ||
| 1071 | * the common code does it only for children of the host bridges | ||
| 1072 | */ | ||
| 1073 | pmac_fixup_phb_resources(); | ||
| 1074 | |||
| 1075 | /* Setup the linkage between OF nodes and PHBs */ | 1035 | /* Setup the linkage between OF nodes and PHBs */ |
| 1076 | pci_devs_phb_init(); | 1036 | pci_devs_phb_init(); |
| 1077 | 1037 | ||
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 40f0008af4d1..a05079b07696 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig | |||
| @@ -7,6 +7,7 @@ config PPC_PS3 | |||
| 7 | select USB_OHCI_BIG_ENDIAN_MMIO | 7 | select USB_OHCI_BIG_ENDIAN_MMIO |
| 8 | select USB_ARCH_HAS_EHCI | 8 | select USB_ARCH_HAS_EHCI |
| 9 | select USB_EHCI_BIG_ENDIAN_MMIO | 9 | select USB_EHCI_BIG_ENDIAN_MMIO |
| 10 | select MEMORY_HOTPLUG | ||
| 10 | help | 11 | help |
| 11 | This option enables support for the Sony PS3 game console | 12 | This option enables support for the Sony PS3 game console |
| 12 | and other platforms using the PS3 hypervisor. | 13 | and other platforms using the PS3 hypervisor. |
| @@ -73,18 +74,12 @@ config PS3_USE_LPAR_ADDR | |||
| 73 | 74 | ||
| 74 | config PS3_VUART | 75 | config PS3_VUART |
| 75 | depends on PPC_PS3 | 76 | depends on PPC_PS3 |
| 76 | bool "PS3 Virtual UART support" if PS3_ADVANCED | 77 | tristate |
| 77 | default y | ||
| 78 | help | ||
| 79 | Include support for the PS3 Virtual UART. | ||
| 80 | |||
| 81 | This support is required for several system services | ||
| 82 | including the System Manager and AV Settings. In | ||
| 83 | general, all users will say Y. | ||
| 84 | 78 | ||
| 85 | config PS3_PS3AV | 79 | config PS3_PS3AV |
| 80 | depends on PPC_PS3 | ||
| 86 | tristate "PS3 AV settings driver" if PS3_ADVANCED | 81 | tristate "PS3 AV settings driver" if PS3_ADVANCED |
| 87 | depends on PS3_VUART | 82 | select PS3_VUART |
| 88 | default y | 83 | default y |
| 89 | help | 84 | help |
| 90 | Include support for the PS3 AV Settings driver. | 85 | Include support for the PS3 AV Settings driver. |
| @@ -93,13 +88,18 @@ config PS3_PS3AV | |||
| 93 | general, all users will say Y or M. | 88 | general, all users will say Y or M. |
| 94 | 89 | ||
| 95 | config PS3_SYS_MANAGER | 90 | config PS3_SYS_MANAGER |
| 96 | bool "PS3 System Manager driver" if PS3_ADVANCED | 91 | depends on PPC_PS3 |
| 97 | depends on PS3_VUART | 92 | tristate "PS3 System Manager driver" if PS3_ADVANCED |
| 98 | default y | 93 | select PS3_VUART |
| 94 | default m | ||
| 99 | help | 95 | help |
| 100 | Include support for the PS3 System Manager. | 96 | Include support for the PS3 System Manager. |
| 101 | 97 | ||
| 102 | This support is required for system control. In | 98 | This support is required for system control. In |
| 103 | general, all users will say Y. | 99 | general, all users will say Y or M. |
| 100 | |||
| 101 | config PS3_STORAGE | ||
| 102 | depends on PPC_PS3 | ||
| 103 | tristate | ||
| 104 | 104 | ||
| 105 | endmenu | 105 | endmenu |
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile index a0048fcf0866..ac1bdf844eca 100644 --- a/arch/powerpc/platforms/ps3/Makefile +++ b/arch/powerpc/platforms/ps3/Makefile | |||
| @@ -4,3 +4,4 @@ obj-y += system-bus.o | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_SMP) += smp.o | 5 | obj-$(CONFIG_SMP) += smp.o |
| 6 | obj-$(CONFIG_SPU_BASE) += spu.o | 6 | obj-$(CONFIG_SPU_BASE) += spu.o |
| 7 | obj-y += device-init.o | ||
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c new file mode 100644 index 000000000000..825ebb2cbc2a --- /dev/null +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
| @@ -0,0 +1,785 @@ | |||
| 1 | /* | ||
| 2 | * PS3 device registration routines. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/freezer.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/kthread.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | |||
| 27 | #include <asm/firmware.h> | ||
| 28 | #include <asm/lv1call.h> | ||
| 29 | #include <asm/ps3stor.h> | ||
| 30 | |||
| 31 | #include "platform.h" | ||
| 32 | |||
| 33 | /** | ||
| 34 | * ps3_setup_gelic_device - Setup and register a gelic device instance. | ||
| 35 | * | ||
| 36 | * Allocates memory for a struct ps3_system_bus_device instance, initialises the | ||
| 37 | * structure members, and registers the device instance with the system bus. | ||
| 38 | */ | ||
| 39 | |||
| 40 | static int __init ps3_setup_gelic_device( | ||
| 41 | const struct ps3_repository_device *repo) | ||
| 42 | { | ||
| 43 | int result; | ||
| 44 | struct layout { | ||
| 45 | struct ps3_system_bus_device dev; | ||
| 46 | struct ps3_dma_region d_region; | ||
| 47 | } *p; | ||
| 48 | |||
| 49 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 50 | |||
| 51 | BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); | ||
| 52 | BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC); | ||
| 53 | |||
| 54 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
| 55 | |||
| 56 | if (!p) { | ||
| 57 | result = -ENOMEM; | ||
| 58 | goto fail_malloc; | ||
| 59 | } | ||
| 60 | |||
| 61 | p->dev.match_id = PS3_MATCH_ID_GELIC; | ||
| 62 | p->dev.dev_type = PS3_DEVICE_TYPE_SB; | ||
| 63 | p->dev.bus_id = repo->bus_id; | ||
| 64 | p->dev.dev_id = repo->dev_id; | ||
| 65 | p->dev.d_region = &p->d_region; | ||
| 66 | |||
| 67 | result = ps3_repository_find_interrupt(repo, | ||
| 68 | PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id); | ||
| 69 | |||
| 70 | if (result) { | ||
| 71 | pr_debug("%s:%d ps3_repository_find_interrupt failed\n", | ||
| 72 | __func__, __LINE__); | ||
| 73 | goto fail_find_interrupt; | ||
| 74 | } | ||
| 75 | |||
| 76 | BUG_ON(p->dev.interrupt_id != 0); | ||
| 77 | |||
| 78 | result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, | ||
| 79 | PS3_DMA_OTHER, NULL, 0); | ||
| 80 | |||
| 81 | if (result) { | ||
| 82 | pr_debug("%s:%d ps3_dma_region_init failed\n", | ||
| 83 | __func__, __LINE__); | ||
| 84 | goto fail_dma_init; | ||
| 85 | } | ||
| 86 | |||
| 87 | result = ps3_system_bus_device_register(&p->dev); | ||
| 88 | |||
| 89 | if (result) { | ||
| 90 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
| 91 | __func__, __LINE__); | ||
| 92 | goto fail_device_register; | ||
| 93 | } | ||
| 94 | |||
| 95 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 96 | return result; | ||
| 97 | |||
| 98 | fail_device_register: | ||
| 99 | fail_dma_init: | ||
| 100 | fail_find_interrupt: | ||
| 101 | kfree(p); | ||
| 102 | fail_malloc: | ||
| 103 | pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); | ||
| 104 | return result; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int __init_refok ps3_setup_uhc_device( | ||
| 108 | const struct ps3_repository_device *repo, enum ps3_match_id match_id, | ||
| 109 | enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type) | ||
| 110 | { | ||
| 111 | int result; | ||
| 112 | struct layout { | ||
| 113 | struct ps3_system_bus_device dev; | ||
| 114 | struct ps3_dma_region d_region; | ||
| 115 | struct ps3_mmio_region m_region; | ||
| 116 | } *p; | ||
| 117 | u64 bus_addr; | ||
| 118 | u64 len; | ||
| 119 | |||
| 120 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 121 | |||
| 122 | BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); | ||
| 123 | BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB); | ||
| 124 | |||
| 125 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
| 126 | |||
| 127 | if (!p) { | ||
| 128 | result = -ENOMEM; | ||
| 129 | goto fail_malloc; | ||
| 130 | } | ||
| 131 | |||
| 132 | p->dev.match_id = match_id; | ||
| 133 | p->dev.dev_type = PS3_DEVICE_TYPE_SB; | ||
| 134 | p->dev.bus_id = repo->bus_id; | ||
| 135 | p->dev.dev_id = repo->dev_id; | ||
| 136 | p->dev.d_region = &p->d_region; | ||
| 137 | p->dev.m_region = &p->m_region; | ||
| 138 | |||
| 139 | result = ps3_repository_find_interrupt(repo, | ||
| 140 | interrupt_type, &p->dev.interrupt_id); | ||
| 141 | |||
| 142 | if (result) { | ||
| 143 | pr_debug("%s:%d ps3_repository_find_interrupt failed\n", | ||
| 144 | __func__, __LINE__); | ||
| 145 | goto fail_find_interrupt; | ||
| 146 | } | ||
| 147 | |||
| 148 | result = ps3_repository_find_reg(repo, reg_type, | ||
| 149 | &bus_addr, &len); | ||
| 150 | |||
| 151 | if (result) { | ||
| 152 | pr_debug("%s:%d ps3_repository_find_reg failed\n", | ||
| 153 | __func__, __LINE__); | ||
| 154 | goto fail_find_reg; | ||
| 155 | } | ||
| 156 | |||
| 157 | result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, | ||
| 158 | PS3_DMA_INTERNAL, NULL, 0); | ||
| 159 | |||
| 160 | if (result) { | ||
| 161 | pr_debug("%s:%d ps3_dma_region_init failed\n", | ||
| 162 | __func__, __LINE__); | ||
| 163 | goto fail_dma_init; | ||
| 164 | } | ||
| 165 | |||
| 166 | result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len, | ||
| 167 | PS3_MMIO_4K); | ||
| 168 | |||
| 169 | if (result) { | ||
| 170 | pr_debug("%s:%d ps3_mmio_region_init failed\n", | ||
| 171 | __func__, __LINE__); | ||
| 172 | goto fail_mmio_init; | ||
| 173 | } | ||
| 174 | |||
| 175 | result = ps3_system_bus_device_register(&p->dev); | ||
| 176 | |||
| 177 | if (result) { | ||
| 178 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
| 179 | __func__, __LINE__); | ||
| 180 | goto fail_device_register; | ||
| 181 | } | ||
| 182 | |||
| 183 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 184 | return result; | ||
| 185 | |||
| 186 | fail_device_register: | ||
| 187 | fail_mmio_init: | ||
| 188 | fail_dma_init: | ||
| 189 | fail_find_reg: | ||
| 190 | fail_find_interrupt: | ||
| 191 | kfree(p); | ||
| 192 | fail_malloc: | ||
| 193 | pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); | ||
| 194 | return result; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int __init ps3_setup_ehci_device( | ||
| 198 | const struct ps3_repository_device *repo) | ||
| 199 | { | ||
| 200 | return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI, | ||
| 201 | PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI); | ||
| 202 | } | ||
| 203 | |||
| 204 | static int __init ps3_setup_ohci_device( | ||
| 205 | const struct ps3_repository_device *repo) | ||
| 206 | { | ||
| 207 | return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI, | ||
| 208 | PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI); | ||
| 209 | } | ||
| 210 | |||
| 211 | static int __init ps3_setup_vuart_device(enum ps3_match_id match_id, | ||
| 212 | unsigned int port_number) | ||
| 213 | { | ||
| 214 | int result; | ||
| 215 | struct layout { | ||
| 216 | struct ps3_system_bus_device dev; | ||
| 217 | } *p; | ||
| 218 | |||
| 219 | pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__, | ||
| 220 | match_id, port_number); | ||
| 221 | |||
| 222 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
| 223 | |||
| 224 | if (!p) | ||
| 225 | return -ENOMEM; | ||
| 226 | |||
| 227 | p->dev.match_id = match_id; | ||
| 228 | p->dev.dev_type = PS3_DEVICE_TYPE_VUART; | ||
| 229 | p->dev.port_number = port_number; | ||
| 230 | |||
| 231 | result = ps3_system_bus_device_register(&p->dev); | ||
| 232 | |||
| 233 | if (result) | ||
| 234 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
| 235 | __func__, __LINE__); | ||
| 236 | |||
| 237 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 238 | return result; | ||
| 239 | } | ||
| 240 | |||
| 241 | static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, | ||
| 242 | unsigned int timeout) | ||
| 243 | { | ||
| 244 | int result = -1; | ||
| 245 | unsigned int retries = 0; | ||
| 246 | u64 status; | ||
| 247 | |||
| 248 | for (retries = 0; retries < timeout; retries++) { | ||
| 249 | result = lv1_storage_check_async_status(dev_id, tag, &status); | ||
| 250 | if (!result) | ||
| 251 | break; | ||
| 252 | |||
| 253 | msleep(1); | ||
| 254 | } | ||
| 255 | |||
| 256 | if (result) | ||
| 257 | pr_debug("%s:%u: check_async_status: %s, status %lx\n", | ||
| 258 | __func__, __LINE__, ps3_result(result), status); | ||
| 259 | |||
| 260 | return result; | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * ps3_storage_wait_for_device - Wait for a storage device to become ready. | ||
| 265 | * @repo: The repository device to wait for. | ||
| 266 | * | ||
| 267 | * Uses the hypervisor's storage device notification mechanism to wait until | ||
| 268 | * a storage device is ready. The device notification mechanism uses a | ||
| 269 | * psuedo device (id = -1) to asynchronously notify the guest when storage | ||
| 270 | * devices become ready. The notification device has a block size of 512 | ||
| 271 | * bytes. | ||
| 272 | */ | ||
| 273 | |||
| 274 | static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | ||
| 275 | { | ||
| 276 | int result; | ||
| 277 | const u64 notification_dev_id = (u64)-1LL; | ||
| 278 | const unsigned int timeout = HZ; | ||
| 279 | u64 lpar; | ||
| 280 | u64 tag; | ||
| 281 | struct { | ||
| 282 | u64 operation_code; /* must be zero */ | ||
| 283 | u64 event_mask; /* 1 = device ready */ | ||
| 284 | } *notify_cmd; | ||
| 285 | struct { | ||
| 286 | u64 event_type; /* notify_device_ready */ | ||
| 287 | u64 bus_id; | ||
| 288 | u64 dev_id; | ||
| 289 | u64 dev_type; | ||
| 290 | u64 dev_port; | ||
| 291 | } *notify_event; | ||
| 292 | enum { | ||
| 293 | notify_device_ready = 1 | ||
| 294 | }; | ||
| 295 | |||
| 296 | pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__, | ||
| 297 | __LINE__, repo->bus_id, repo->dev_id, repo->dev_type); | ||
| 298 | |||
| 299 | notify_cmd = kzalloc(512, GFP_KERNEL); | ||
| 300 | notify_event = (void *)notify_cmd; | ||
| 301 | if (!notify_cmd) | ||
| 302 | return -ENOMEM; | ||
| 303 | |||
| 304 | lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd)); | ||
| 305 | |||
| 306 | result = lv1_open_device(repo->bus_id, notification_dev_id, 0); | ||
| 307 | if (result) { | ||
| 308 | printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, | ||
| 309 | __LINE__, ps3_result(result)); | ||
| 310 | result = -ENODEV; | ||
| 311 | goto fail_free; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Setup and write the request for device notification. */ | ||
| 315 | |||
| 316 | notify_cmd->operation_code = 0; /* must be zero */ | ||
| 317 | notify_cmd->event_mask = 0x01; /* device ready */ | ||
| 318 | |||
| 319 | result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, | ||
| 320 | &tag); | ||
| 321 | if (result) { | ||
| 322 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, | ||
| 323 | ps3_result(result)); | ||
| 324 | result = -ENODEV; | ||
| 325 | goto fail_close; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* Wait for the write completion */ | ||
| 329 | |||
| 330 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
| 331 | timeout); | ||
| 332 | if (result) { | ||
| 333 | printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, | ||
| 334 | __LINE__, ps3_result(result)); | ||
| 335 | result = -ENODEV; | ||
| 336 | goto fail_close; | ||
| 337 | } | ||
| 338 | |||
| 339 | /* Loop here processing the requested notification events. */ | ||
| 340 | |||
| 341 | result = -ENODEV; | ||
| 342 | while (1) { | ||
| 343 | memset(notify_event, 0, sizeof(*notify_event)); | ||
| 344 | |||
| 345 | result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, | ||
| 346 | lpar, &tag); | ||
| 347 | if (result) { | ||
| 348 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, | ||
| 349 | __LINE__, ps3_result(result)); | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | |||
| 353 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
| 354 | timeout); | ||
| 355 | if (result) { | ||
| 356 | printk(KERN_ERR "%s:%u: read not completed %s\n", | ||
| 357 | __func__, __LINE__, ps3_result(result)); | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | |||
| 361 | if (notify_event->event_type != notify_device_ready || | ||
| 362 | notify_event->bus_id != repo->bus_id) { | ||
| 363 | pr_debug("%s:%u: bad notify_event: event %lu, " | ||
| 364 | "dev_id %lu, dev_type %lu\n", | ||
| 365 | __func__, __LINE__, notify_event->event_type, | ||
| 366 | notify_event->dev_id, notify_event->dev_type); | ||
| 367 | break; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (notify_event->dev_id == repo->dev_id && | ||
| 371 | notify_event->dev_type == repo->dev_type) { | ||
| 372 | pr_debug("%s:%u: device ready: dev_id %u\n", __func__, | ||
| 373 | __LINE__, repo->dev_id); | ||
| 374 | result = 0; | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | |||
| 378 | if (notify_event->dev_id == repo->dev_id && | ||
| 379 | notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { | ||
| 380 | pr_debug("%s:%u: no access: dev_id %u\n", __func__, | ||
| 381 | __LINE__, repo->dev_id); | ||
| 382 | break; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | fail_close: | ||
| 387 | lv1_close_device(repo->bus_id, notification_dev_id); | ||
| 388 | fail_free: | ||
| 389 | kfree(notify_cmd); | ||
| 390 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
| 391 | return result; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | ||
| 395 | enum ps3_match_id match_id) | ||
| 396 | { | ||
| 397 | int result; | ||
| 398 | struct ps3_storage_device *p; | ||
| 399 | u64 port, blk_size, num_blocks; | ||
| 400 | unsigned int num_regions, i; | ||
| 401 | |||
| 402 | pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id); | ||
| 403 | |||
| 404 | result = ps3_repository_read_stor_dev_info(repo->bus_index, | ||
| 405 | repo->dev_index, &port, | ||
| 406 | &blk_size, &num_blocks, | ||
| 407 | &num_regions); | ||
| 408 | if (result) { | ||
| 409 | printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n", | ||
| 410 | __func__, __LINE__, result); | ||
| 411 | return -ENODEV; | ||
| 412 | } | ||
| 413 | |||
| 414 | pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu " | ||
| 415 | "num_regions %u\n", __func__, __LINE__, repo->bus_index, | ||
| 416 | repo->dev_index, port, blk_size, num_blocks, num_regions); | ||
| 417 | |||
| 418 | p = kzalloc(sizeof(struct ps3_storage_device) + | ||
| 419 | num_regions * sizeof(struct ps3_storage_region), | ||
| 420 | GFP_KERNEL); | ||
| 421 | if (!p) { | ||
| 422 | result = -ENOMEM; | ||
| 423 | goto fail_malloc; | ||
| 424 | } | ||
| 425 | |||
| 426 | p->sbd.match_id = match_id; | ||
| 427 | p->sbd.dev_type = PS3_DEVICE_TYPE_SB; | ||
| 428 | p->sbd.bus_id = repo->bus_id; | ||
| 429 | p->sbd.dev_id = repo->dev_id; | ||
| 430 | p->sbd.d_region = &p->dma_region; | ||
| 431 | p->blk_size = blk_size; | ||
| 432 | p->num_regions = num_regions; | ||
| 433 | |||
| 434 | result = ps3_repository_find_interrupt(repo, | ||
| 435 | PS3_INTERRUPT_TYPE_EVENT_PORT, | ||
| 436 | &p->sbd.interrupt_id); | ||
| 437 | if (result) { | ||
| 438 | printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__, | ||
| 439 | __LINE__, result); | ||
| 440 | result = -ENODEV; | ||
| 441 | goto fail_find_interrupt; | ||
| 442 | } | ||
| 443 | |||
| 444 | /* FIXME: Arrange to only do this on a 'cold' boot */ | ||
| 445 | |||
| 446 | result = ps3_storage_wait_for_device(repo); | ||
| 447 | if (result) { | ||
| 448 | printk(KERN_ERR "%s:%u: storage_notification failed %d\n", | ||
| 449 | __func__, __LINE__, result); | ||
| 450 | result = -ENODEV; | ||
| 451 | goto fail_probe_notification; | ||
| 452 | } | ||
| 453 | |||
| 454 | for (i = 0; i < num_regions; i++) { | ||
| 455 | unsigned int id; | ||
| 456 | u64 start, size; | ||
| 457 | |||
| 458 | result = ps3_repository_read_stor_dev_region(repo->bus_index, | ||
| 459 | repo->dev_index, | ||
| 460 | i, &id, &start, | ||
| 461 | &size); | ||
| 462 | if (result) { | ||
| 463 | printk(KERN_ERR | ||
| 464 | "%s:%u: read_stor_dev_region failed %d\n", | ||
| 465 | __func__, __LINE__, result); | ||
| 466 | result = -ENODEV; | ||
| 467 | goto fail_read_region; | ||
| 468 | } | ||
| 469 | pr_debug("%s:%u: region %u: id %u start %lu size %lu\n", | ||
| 470 | __func__, __LINE__, i, id, start, size); | ||
| 471 | |||
| 472 | p->regions[i].id = id; | ||
| 473 | p->regions[i].start = start; | ||
| 474 | p->regions[i].size = size; | ||
| 475 | } | ||
| 476 | |||
| 477 | result = ps3_system_bus_device_register(&p->sbd); | ||
| 478 | if (result) { | ||
| 479 | pr_debug("%s:%u ps3_system_bus_device_register failed\n", | ||
| 480 | __func__, __LINE__); | ||
| 481 | goto fail_device_register; | ||
| 482 | } | ||
| 483 | |||
| 484 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
| 485 | return 0; | ||
| 486 | |||
| 487 | fail_device_register: | ||
| 488 | fail_read_region: | ||
| 489 | fail_probe_notification: | ||
| 490 | fail_find_interrupt: | ||
| 491 | kfree(p); | ||
| 492 | fail_malloc: | ||
| 493 | pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__); | ||
| 494 | return result; | ||
| 495 | } | ||
| 496 | |||
| 497 | static int __init ps3_register_vuart_devices(void) | ||
| 498 | { | ||
| 499 | int result; | ||
| 500 | unsigned int port_number; | ||
| 501 | |||
| 502 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 503 | |||
| 504 | result = ps3_repository_read_vuart_av_port(&port_number); | ||
| 505 | if (result) | ||
| 506 | port_number = 0; /* av default */ | ||
| 507 | |||
| 508 | result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number); | ||
| 509 | WARN_ON(result); | ||
| 510 | |||
| 511 | result = ps3_repository_read_vuart_sysmgr_port(&port_number); | ||
| 512 | if (result) | ||
| 513 | port_number = 2; /* sysmgr default */ | ||
| 514 | |||
| 515 | result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER, | ||
| 516 | port_number); | ||
| 517 | WARN_ON(result); | ||
| 518 | |||
| 519 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 520 | return result; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int __init ps3_register_sound_devices(void) | ||
| 524 | { | ||
| 525 | int result; | ||
| 526 | struct layout { | ||
| 527 | struct ps3_system_bus_device dev; | ||
| 528 | struct ps3_dma_region d_region; | ||
| 529 | struct ps3_mmio_region m_region; | ||
| 530 | } *p; | ||
| 531 | |||
| 532 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 533 | |||
| 534 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 535 | if (!p) | ||
| 536 | return -ENOMEM; | ||
| 537 | |||
| 538 | p->dev.match_id = PS3_MATCH_ID_SOUND; | ||
| 539 | p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; | ||
| 540 | p->dev.d_region = &p->d_region; | ||
| 541 | p->dev.m_region = &p->m_region; | ||
| 542 | |||
| 543 | result = ps3_system_bus_device_register(&p->dev); | ||
| 544 | |||
| 545 | if (result) | ||
| 546 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
| 547 | __func__, __LINE__); | ||
| 548 | |||
| 549 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 550 | return result; | ||
| 551 | } | ||
| 552 | |||
| 553 | static int __init ps3_register_graphics_devices(void) | ||
| 554 | { | ||
| 555 | int result; | ||
| 556 | struct layout { | ||
| 557 | struct ps3_system_bus_device dev; | ||
| 558 | } *p; | ||
| 559 | |||
| 560 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 561 | |||
| 562 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
| 563 | |||
| 564 | if (!p) | ||
| 565 | return -ENOMEM; | ||
| 566 | |||
| 567 | p->dev.match_id = PS3_MATCH_ID_GRAPHICS; | ||
| 568 | p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; | ||
| 569 | |||
| 570 | result = ps3_system_bus_device_register(&p->dev); | ||
| 571 | |||
| 572 | if (result) | ||
| 573 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
| 574 | __func__, __LINE__); | ||
| 575 | |||
| 576 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 577 | return result; | ||
| 578 | } | ||
| 579 | |||
| 580 | /** | ||
| 581 | * ps3_register_repository_device - Register a device from the repositiory info. | ||
| 582 | * | ||
| 583 | */ | ||
| 584 | |||
| 585 | static int ps3_register_repository_device( | ||
| 586 | const struct ps3_repository_device *repo) | ||
| 587 | { | ||
| 588 | int result; | ||
| 589 | |||
| 590 | switch (repo->dev_type) { | ||
| 591 | case PS3_DEV_TYPE_SB_GELIC: | ||
| 592 | result = ps3_setup_gelic_device(repo); | ||
| 593 | if (result) { | ||
| 594 | pr_debug("%s:%d ps3_setup_gelic_device failed\n", | ||
| 595 | __func__, __LINE__); | ||
| 596 | } | ||
| 597 | break; | ||
| 598 | case PS3_DEV_TYPE_SB_USB: | ||
| 599 | |||
| 600 | /* Each USB device has both an EHCI and an OHCI HC */ | ||
| 601 | |||
| 602 | result = ps3_setup_ehci_device(repo); | ||
| 603 | |||
| 604 | if (result) { | ||
| 605 | pr_debug("%s:%d ps3_setup_ehci_device failed\n", | ||
| 606 | __func__, __LINE__); | ||
| 607 | } | ||
| 608 | |||
| 609 | result = ps3_setup_ohci_device(repo); | ||
| 610 | |||
| 611 | if (result) { | ||
| 612 | pr_debug("%s:%d ps3_setup_ohci_device failed\n", | ||
| 613 | __func__, __LINE__); | ||
| 614 | } | ||
| 615 | break; | ||
| 616 | case PS3_DEV_TYPE_STOR_DISK: | ||
| 617 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK); | ||
| 618 | |||
| 619 | /* Some devices are not accessable from the Other OS lpar. */ | ||
| 620 | if (result == -ENODEV) { | ||
| 621 | result = 0; | ||
| 622 | pr_debug("%s:%u: not accessable\n", __func__, | ||
| 623 | __LINE__); | ||
| 624 | } | ||
| 625 | |||
| 626 | if (result) | ||
| 627 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
| 628 | __func__, __LINE__); | ||
| 629 | break; | ||
| 630 | |||
| 631 | case PS3_DEV_TYPE_STOR_ROM: | ||
| 632 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM); | ||
| 633 | if (result) | ||
| 634 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
| 635 | __func__, __LINE__); | ||
| 636 | break; | ||
| 637 | |||
| 638 | case PS3_DEV_TYPE_STOR_FLASH: | ||
| 639 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH); | ||
| 640 | if (result) | ||
| 641 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
| 642 | __func__, __LINE__); | ||
| 643 | break; | ||
| 644 | |||
| 645 | default: | ||
| 646 | result = 0; | ||
| 647 | pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__, | ||
| 648 | repo->dev_type); | ||
| 649 | } | ||
| 650 | |||
| 651 | return result; | ||
| 652 | } | ||
| 653 | |||
| 654 | /** | ||
| 655 | * ps3_probe_thread - Background repository probing at system startup. | ||
| 656 | * | ||
| 657 | * This implementation only supports background probing on a single bus. | ||
| 658 | */ | ||
| 659 | |||
| 660 | static int ps3_probe_thread(void *data) | ||
| 661 | { | ||
| 662 | struct ps3_repository_device *repo = data; | ||
| 663 | int result; | ||
| 664 | unsigned int ms = 250; | ||
| 665 | |||
| 666 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); | ||
| 667 | |||
| 668 | do { | ||
| 669 | try_to_freeze(); | ||
| 670 | |||
| 671 | pr_debug("%s:%u: probing...\n", __func__, __LINE__); | ||
| 672 | |||
| 673 | do { | ||
| 674 | result = ps3_repository_find_device(repo); | ||
| 675 | |||
| 676 | if (result == -ENODEV) | ||
| 677 | pr_debug("%s:%u: nothing new\n", __func__, | ||
| 678 | __LINE__); | ||
| 679 | else if (result) | ||
| 680 | pr_debug("%s:%u: find device error.\n", | ||
| 681 | __func__, __LINE__); | ||
| 682 | else { | ||
| 683 | pr_debug("%s:%u: found device\n", __func__, | ||
| 684 | __LINE__); | ||
| 685 | ps3_register_repository_device(repo); | ||
| 686 | ps3_repository_bump_device(repo); | ||
| 687 | ms = 250; | ||
| 688 | } | ||
| 689 | } while (!result); | ||
| 690 | |||
| 691 | pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms); | ||
| 692 | |||
| 693 | if ( ms > 60000) | ||
| 694 | break; | ||
| 695 | |||
| 696 | msleep_interruptible(ms); | ||
| 697 | |||
| 698 | /* An exponential backoff. */ | ||
| 699 | ms <<= 1; | ||
| 700 | |||
| 701 | } while (!kthread_should_stop()); | ||
| 702 | |||
| 703 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); | ||
| 704 | |||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 708 | /** | ||
| 709 | * ps3_start_probe_thread - Starts the background probe thread. | ||
| 710 | * | ||
| 711 | */ | ||
| 712 | |||
| 713 | static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | ||
| 714 | { | ||
| 715 | int result; | ||
| 716 | struct task_struct *task; | ||
| 717 | static struct ps3_repository_device repo; /* must be static */ | ||
| 718 | |||
| 719 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 720 | |||
| 721 | memset(&repo, 0, sizeof(repo)); | ||
| 722 | |||
| 723 | repo.bus_type = bus_type; | ||
| 724 | |||
| 725 | result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); | ||
| 726 | |||
| 727 | if (result) { | ||
| 728 | printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result); | ||
| 729 | return -ENODEV; | ||
| 730 | } | ||
| 731 | |||
| 732 | result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); | ||
| 733 | |||
| 734 | if (result) { | ||
| 735 | printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__, | ||
| 736 | result); | ||
| 737 | return -ENODEV; | ||
| 738 | } | ||
| 739 | |||
| 740 | task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); | ||
| 741 | |||
| 742 | if (IS_ERR(task)) { | ||
| 743 | result = PTR_ERR(task); | ||
| 744 | printk(KERN_ERR "%s: kthread_run failed %d\n", __func__, | ||
| 745 | result); | ||
| 746 | return result; | ||
| 747 | } | ||
| 748 | |||
| 749 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | |||
| 753 | /** | ||
| 754 | * ps3_register_devices - Probe the system and register devices found. | ||
| 755 | * | ||
| 756 | * A device_initcall() routine. | ||
| 757 | */ | ||
| 758 | |||
| 759 | static int __init ps3_register_devices(void) | ||
| 760 | { | ||
| 761 | int result; | ||
| 762 | |||
| 763 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
| 764 | return -ENODEV; | ||
| 765 | |||
| 766 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 767 | |||
| 768 | /* ps3_repository_dump_bus_info(); */ | ||
| 769 | |||
| 770 | result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE); | ||
| 771 | |||
| 772 | ps3_register_vuart_devices(); | ||
| 773 | |||
| 774 | ps3_register_graphics_devices(); | ||
| 775 | |||
| 776 | ps3_repository_find_devices(PS3_BUS_TYPE_SB, | ||
| 777 | ps3_register_repository_device); | ||
| 778 | |||
| 779 | ps3_register_sound_devices(); | ||
| 780 | |||
| 781 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 782 | return 0; | ||
| 783 | } | ||
| 784 | |||
| 785 | device_initcall(ps3_register_devices); | ||
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index a1409e450c70..5d2e176a1b18 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
| @@ -29,12 +29,12 @@ | |||
| 29 | #include "platform.h" | 29 | #include "platform.h" |
| 30 | 30 | ||
| 31 | #if defined(DEBUG) | 31 | #if defined(DEBUG) |
| 32 | #define DBG(fmt...) udbg_printf(fmt) | 32 | #define DBG udbg_printf |
| 33 | #else | 33 | #else |
| 34 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 34 | #define DBG pr_debug |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | static hpte_t *htab; | 37 | static struct hash_pte *htab; |
| 38 | static unsigned long htab_addr; | 38 | static unsigned long htab_addr; |
| 39 | static unsigned char *bolttab; | 39 | static unsigned char *bolttab; |
| 40 | static unsigned char *inusetab; | 40 | static unsigned char *inusetab; |
| @@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(ps3_bolttab_lock); | |||
| 44 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ | 44 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ |
| 45 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | 45 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) |
| 46 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, | 46 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, |
| 47 | unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize, | 47 | unsigned long group, unsigned long bitmap, struct hash_pte lhpte, |
| 48 | unsigned long slot, const char* func, int line) | 48 | int psize, unsigned long slot, const char* func, int line) |
| 49 | { | 49 | { |
| 50 | DBG("%s:%d: pa = %lxh\n", func, line, pa); | 50 | DBG("%s:%d: pa = %lxh\n", func, line, pa); |
| 51 | DBG("%s:%d: lpar = %lxh\n", func, line, | 51 | DBG("%s:%d: lpar = %lxh\n", func, line, |
| @@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) | 63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) |
| 64 | { | 64 | { |
| 65 | unsigned long slot; | 65 | unsigned long slot; |
| 66 | hpte_t lhpte; | 66 | struct hash_pte lhpte; |
| 67 | int secondary = 0; | 67 | int secondary = 0; |
| 68 | unsigned long result; | 68 | unsigned long result; |
| 69 | unsigned long bitmap; | 69 | unsigned long bitmap; |
| @@ -234,10 +234,17 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 234 | 234 | ||
| 235 | static void ps3_hpte_clear(void) | 235 | static void ps3_hpte_clear(void) |
| 236 | { | 236 | { |
| 237 | /* Make sure to clean up the frame buffer device first */ | 237 | int result; |
| 238 | ps3fb_cleanup(); | ||
| 239 | 238 | ||
| 240 | lv1_unmap_htab(htab_addr); | 239 | DBG(" -> %s:%d\n", __func__, __LINE__); |
| 240 | |||
| 241 | result = lv1_unmap_htab(htab_addr); | ||
| 242 | BUG_ON(result); | ||
| 243 | |||
| 244 | ps3_mm_shutdown(); | ||
| 245 | ps3_mm_vas_destroy(); | ||
| 246 | |||
| 247 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
| 241 | } | 248 | } |
| 242 | 249 | ||
| 243 | void __init ps3_hpte_init(unsigned long htab_size) | 250 | void __init ps3_hpte_init(unsigned long htab_size) |
| @@ -255,7 +262,7 @@ void __init ps3_hpte_init(unsigned long htab_size) | |||
| 255 | 262 | ||
| 256 | ppc64_pft_size = __ilog2(htab_size); | 263 | ppc64_pft_size = __ilog2(htab_size); |
| 257 | 264 | ||
| 258 | bitmap_size = htab_size / sizeof(hpte_t) / 8; | 265 | bitmap_size = htab_size / sizeof(struct hash_pte) / 8; |
| 259 | 266 | ||
| 260 | bolttab = __va(lmb_alloc(bitmap_size, 1)); | 267 | bolttab = __va(lmb_alloc(bitmap_size, 1)); |
| 261 | inusetab = __va(lmb_alloc(bitmap_size, 1)); | 268 | inusetab = __va(lmb_alloc(bitmap_size, 1)); |
| @@ -273,8 +280,8 @@ void __init ps3_map_htab(void) | |||
| 273 | 280 | ||
| 274 | result = lv1_map_htab(0, &htab_addr); | 281 | result = lv1_map_htab(0, &htab_addr); |
| 275 | 282 | ||
| 276 | htab = (hpte_t *)__ioremap(htab_addr, htab_size, | 283 | htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size, |
| 277 | pgprot_val(PAGE_READONLY_X)); | 284 | pgprot_val(PAGE_READONLY_X)); |
| 278 | 285 | ||
| 279 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, | 286 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, |
| 280 | htab_addr, (unsigned long)htab); | 287 | htab_addr, (unsigned long)htab); |
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index ec9030dbb5f1..67e32ec9b37e 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
| @@ -30,9 +30,9 @@ | |||
| 30 | #include "platform.h" | 30 | #include "platform.h" |
| 31 | 31 | ||
| 32 | #if defined(DEBUG) | 32 | #if defined(DEBUG) |
| 33 | #define DBG(fmt...) udbg_printf(fmt) | 33 | #define DBG udbg_printf |
| 34 | #else | 34 | #else |
| 35 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 35 | #define DBG pr_debug |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | /** | 38 | /** |
| @@ -78,19 +78,85 @@ struct ps3_bmp { | |||
| 78 | /** | 78 | /** |
| 79 | * struct ps3_private - a per cpu data structure | 79 | * struct ps3_private - a per cpu data structure |
| 80 | * @bmp: ps3_bmp structure | 80 | * @bmp: ps3_bmp structure |
| 81 | * @node: HV logical_ppe_id | 81 | * @ppe_id: HV logical_ppe_id |
| 82 | * @cpu: HV thread_id | 82 | * @thread_id: HV thread_id |
| 83 | */ | 83 | */ |
| 84 | 84 | ||
| 85 | struct ps3_private { | 85 | struct ps3_private { |
| 86 | struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); | 86 | struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); |
| 87 | u64 node; | 87 | u64 ppe_id; |
| 88 | unsigned int cpu; | 88 | u64 thread_id; |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | static DEFINE_PER_CPU(struct ps3_private, ps3_private); | 91 | static DEFINE_PER_CPU(struct ps3_private, ps3_private); |
| 92 | 92 | ||
| 93 | /** | 93 | /** |
| 94 | * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp. | ||
| 95 | * @virq: The assigned Linux virq. | ||
| 96 | * | ||
| 97 | * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). | ||
| 98 | */ | ||
| 99 | |||
| 100 | static void ps3_chip_mask(unsigned int virq) | ||
| 101 | { | ||
| 102 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 103 | unsigned long flags; | ||
| 104 | |||
| 105 | pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, | ||
| 106 | pd->thread_id, virq); | ||
| 107 | |||
| 108 | local_irq_save(flags); | ||
| 109 | clear_bit(63 - virq, &pd->bmp.mask); | ||
| 110 | lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); | ||
| 111 | local_irq_restore(flags); | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp. | ||
| 116 | * @virq: The assigned Linux virq. | ||
| 117 | * | ||
| 118 | * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). | ||
| 119 | */ | ||
| 120 | |||
| 121 | static void ps3_chip_unmask(unsigned int virq) | ||
| 122 | { | ||
| 123 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 124 | unsigned long flags; | ||
| 125 | |||
| 126 | pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, | ||
| 127 | pd->thread_id, virq); | ||
| 128 | |||
| 129 | local_irq_save(flags); | ||
| 130 | set_bit(63 - virq, &pd->bmp.mask); | ||
| 131 | lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); | ||
| 132 | local_irq_restore(flags); | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * ps3_chip_eoi - HV end-of-interrupt. | ||
| 137 | * @virq: The assigned Linux virq. | ||
| 138 | * | ||
| 139 | * Calls lv1_end_of_interrupt_ext(). | ||
| 140 | */ | ||
| 141 | |||
| 142 | static void ps3_chip_eoi(unsigned int virq) | ||
| 143 | { | ||
| 144 | const struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 145 | lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq); | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip. | ||
| 150 | */ | ||
| 151 | |||
| 152 | static struct irq_chip ps3_irq_chip = { | ||
| 153 | .typename = "ps3", | ||
| 154 | .mask = ps3_chip_mask, | ||
| 155 | .unmask = ps3_chip_unmask, | ||
| 156 | .eoi = ps3_chip_eoi, | ||
| 157 | }; | ||
| 158 | |||
| 159 | /** | ||
| 94 | * ps3_virq_setup - virq related setup. | 160 | * ps3_virq_setup - virq related setup. |
| 95 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be | 161 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be |
| 96 | * serviced on. | 162 | * serviced on. |
| @@ -134,6 +200,8 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, | |||
| 134 | goto fail_set; | 200 | goto fail_set; |
| 135 | } | 201 | } |
| 136 | 202 | ||
| 203 | ps3_chip_mask(*virq); | ||
| 204 | |||
| 137 | return result; | 205 | return result; |
| 138 | 206 | ||
| 139 | fail_set: | 207 | fail_set: |
| @@ -153,8 +221,8 @@ int ps3_virq_destroy(unsigned int virq) | |||
| 153 | { | 221 | { |
| 154 | const struct ps3_private *pd = get_irq_chip_data(virq); | 222 | const struct ps3_private *pd = get_irq_chip_data(virq); |
| 155 | 223 | ||
| 156 | pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, | 224 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, |
| 157 | pd->node, pd->cpu, virq); | 225 | __LINE__, pd->ppe_id, pd->thread_id, virq); |
| 158 | 226 | ||
| 159 | set_irq_chip_data(virq, NULL); | 227 | set_irq_chip_data(virq, NULL); |
| 160 | irq_dispose_mapping(virq); | 228 | irq_dispose_mapping(virq); |
| @@ -190,7 +258,8 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, | |||
| 190 | 258 | ||
| 191 | /* Binds outlet to cpu + virq. */ | 259 | /* Binds outlet to cpu + virq. */ |
| 192 | 260 | ||
| 193 | result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); | 261 | result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq, |
| 262 | outlet, 0); | ||
| 194 | 263 | ||
| 195 | if (result) { | 264 | if (result) { |
| 196 | pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", | 265 | pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", |
| @@ -222,10 +291,12 @@ int ps3_irq_plug_destroy(unsigned int virq) | |||
| 222 | int result; | 291 | int result; |
| 223 | const struct ps3_private *pd = get_irq_chip_data(virq); | 292 | const struct ps3_private *pd = get_irq_chip_data(virq); |
| 224 | 293 | ||
| 225 | pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, | 294 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, |
| 226 | pd->node, pd->cpu, virq); | 295 | __LINE__, pd->ppe_id, pd->thread_id, virq); |
| 296 | |||
| 297 | ps3_chip_mask(virq); | ||
| 227 | 298 | ||
| 228 | result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); | 299 | result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq); |
| 229 | 300 | ||
| 230 | if (result) | 301 | if (result) |
| 231 | pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", | 302 | pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", |
| @@ -282,7 +353,9 @@ int ps3_event_receive_port_destroy(unsigned int virq) | |||
| 282 | { | 353 | { |
| 283 | int result; | 354 | int result; |
| 284 | 355 | ||
| 285 | pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); | 356 | pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq); |
| 357 | |||
| 358 | ps3_chip_mask(virq); | ||
| 286 | 359 | ||
| 287 | result = lv1_destruct_event_receive_port(virq_to_hw(virq)); | 360 | result = lv1_destruct_event_receive_port(virq_to_hw(virq)); |
| 288 | 361 | ||
| @@ -290,17 +363,14 @@ int ps3_event_receive_port_destroy(unsigned int virq) | |||
| 290 | pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", | 363 | pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", |
| 291 | __func__, __LINE__, ps3_result(result)); | 364 | __func__, __LINE__, ps3_result(result)); |
| 292 | 365 | ||
| 293 | /* lv1_destruct_event_receive_port() destroys the IRQ plug, | 366 | /* |
| 294 | * so don't call ps3_irq_plug_destroy() here. | 367 | * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu() |
| 368 | * calls from interrupt context (smp_call_function) when kexecing. | ||
| 295 | */ | 369 | */ |
| 296 | 370 | ||
| 297 | result = ps3_virq_destroy(virq); | ||
| 298 | BUG_ON(result); | ||
| 299 | |||
| 300 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 371 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
| 301 | return result; | 372 | return result; |
| 302 | } | 373 | } |
| 303 | EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); | ||
| 304 | 374 | ||
| 305 | int ps3_send_event_locally(unsigned int virq) | 375 | int ps3_send_event_locally(unsigned int virq) |
| 306 | { | 376 | { |
| @@ -311,17 +381,15 @@ int ps3_send_event_locally(unsigned int virq) | |||
| 311 | * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. | 381 | * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. |
| 312 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be | 382 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be |
| 313 | * serviced on. | 383 | * serviced on. |
| 314 | * @did: The HV device identifier read from the system repository. | 384 | * @dev: The system bus device instance. |
| 315 | * @interrupt_id: The device interrupt id read from the system repository. | ||
| 316 | * @virq: The assigned Linux virq. | 385 | * @virq: The assigned Linux virq. |
| 317 | * | 386 | * |
| 318 | * An event irq represents a virtual device interrupt. The interrupt_id | 387 | * An event irq represents a virtual device interrupt. The interrupt_id |
| 319 | * coresponds to the software interrupt number. | 388 | * coresponds to the software interrupt number. |
| 320 | */ | 389 | */ |
| 321 | 390 | ||
| 322 | int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | 391 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, |
| 323 | const struct ps3_device_id *did, unsigned int interrupt_id, | 392 | enum ps3_cpu_binding cpu, unsigned int *virq) |
| 324 | unsigned int *virq) | ||
| 325 | { | 393 | { |
| 326 | /* this should go in system-bus.c */ | 394 | /* this should go in system-bus.c */ |
| 327 | 395 | ||
| @@ -332,8 +400,8 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | |||
| 332 | if (result) | 400 | if (result) |
| 333 | return result; | 401 | return result; |
| 334 | 402 | ||
| 335 | result = lv1_connect_interrupt_event_receive_port(did->bus_id, | 403 | result = lv1_connect_interrupt_event_receive_port(dev->bus_id, |
| 336 | did->dev_id, virq_to_hw(*virq), interrupt_id); | 404 | dev->dev_id, virq_to_hw(*virq), dev->interrupt_id); |
| 337 | 405 | ||
| 338 | if (result) { | 406 | if (result) { |
| 339 | pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" | 407 | pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" |
| @@ -345,24 +413,24 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | |||
| 345 | } | 413 | } |
| 346 | 414 | ||
| 347 | pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | 415 | pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, |
| 348 | interrupt_id, *virq); | 416 | dev->interrupt_id, *virq); |
| 349 | 417 | ||
| 350 | return 0; | 418 | return 0; |
| 351 | } | 419 | } |
| 352 | EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); | 420 | EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); |
| 353 | 421 | ||
| 354 | int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | 422 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, |
| 355 | unsigned int interrupt_id, unsigned int virq) | 423 | unsigned int virq) |
| 356 | { | 424 | { |
| 357 | /* this should go in system-bus.c */ | 425 | /* this should go in system-bus.c */ |
| 358 | 426 | ||
| 359 | int result; | 427 | int result; |
| 360 | 428 | ||
| 361 | pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | 429 | pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, |
| 362 | interrupt_id, virq); | 430 | dev->interrupt_id, virq); |
| 363 | 431 | ||
| 364 | result = lv1_disconnect_interrupt_event_receive_port(did->bus_id, | 432 | result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id, |
| 365 | did->dev_id, virq_to_hw(virq), interrupt_id); | 433 | dev->dev_id, virq_to_hw(virq), dev->interrupt_id); |
| 366 | 434 | ||
| 367 | if (result) | 435 | if (result) |
| 368 | pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" | 436 | pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" |
| @@ -372,6 +440,14 @@ int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | |||
| 372 | result = ps3_event_receive_port_destroy(virq); | 440 | result = ps3_event_receive_port_destroy(virq); |
| 373 | BUG_ON(result); | 441 | BUG_ON(result); |
| 374 | 442 | ||
| 443 | /* | ||
| 444 | * ps3_event_receive_port_destroy() destroys the IRQ plug, | ||
| 445 | * so don't call ps3_irq_plug_destroy() here. | ||
| 446 | */ | ||
| 447 | |||
| 448 | result = ps3_virq_destroy(virq); | ||
| 449 | BUG_ON(result); | ||
| 450 | |||
| 375 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 451 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
| 376 | return result; | 452 | return result; |
| 377 | } | 453 | } |
| @@ -412,16 +488,24 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup); | |||
| 412 | int ps3_io_irq_destroy(unsigned int virq) | 488 | int ps3_io_irq_destroy(unsigned int virq) |
| 413 | { | 489 | { |
| 414 | int result; | 490 | int result; |
| 491 | unsigned long outlet = virq_to_hw(virq); | ||
| 415 | 492 | ||
| 416 | result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); | 493 | ps3_chip_mask(virq); |
| 417 | 494 | ||
| 418 | if (result) | 495 | /* |
| 419 | pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", | 496 | * lv1_destruct_io_irq_outlet() will destroy the IRQ plug, |
| 420 | __func__, __LINE__, ps3_result(result)); | 497 | * so call ps3_irq_plug_destroy() first. |
| 498 | */ | ||
| 421 | 499 | ||
| 422 | result = ps3_irq_plug_destroy(virq); | 500 | result = ps3_irq_plug_destroy(virq); |
| 423 | BUG_ON(result); | 501 | BUG_ON(result); |
| 424 | 502 | ||
| 503 | result = lv1_destruct_io_irq_outlet(outlet); | ||
| 504 | |||
| 505 | if (result) | ||
| 506 | pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", | ||
| 507 | __func__, __LINE__, ps3_result(result)); | ||
| 508 | |||
| 425 | return result; | 509 | return result; |
| 426 | } | 510 | } |
| 427 | EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); | 511 | EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); |
| @@ -461,11 +545,13 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, | |||
| 461 | 545 | ||
| 462 | return result; | 546 | return result; |
| 463 | } | 547 | } |
| 548 | EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup); | ||
| 464 | 549 | ||
| 465 | int ps3_vuart_irq_destroy(unsigned int virq) | 550 | int ps3_vuart_irq_destroy(unsigned int virq) |
| 466 | { | 551 | { |
| 467 | int result; | 552 | int result; |
| 468 | 553 | ||
| 554 | ps3_chip_mask(virq); | ||
| 469 | result = lv1_deconfigure_virtual_uart_irq(); | 555 | result = lv1_deconfigure_virtual_uart_irq(); |
| 470 | 556 | ||
| 471 | if (result) { | 557 | if (result) { |
| @@ -479,6 +565,7 @@ int ps3_vuart_irq_destroy(unsigned int virq) | |||
| 479 | 565 | ||
| 480 | return result; | 566 | return result; |
| 481 | } | 567 | } |
| 568 | EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy); | ||
| 482 | 569 | ||
| 483 | /** | 570 | /** |
| 484 | * ps3_spe_irq_setup - Setup an spe virq. | 571 | * ps3_spe_irq_setup - Setup an spe virq. |
| @@ -514,9 +601,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, | |||
| 514 | 601 | ||
| 515 | int ps3_spe_irq_destroy(unsigned int virq) | 602 | int ps3_spe_irq_destroy(unsigned int virq) |
| 516 | { | 603 | { |
| 517 | int result = ps3_irq_plug_destroy(virq); | 604 | int result; |
| 605 | |||
| 606 | ps3_chip_mask(virq); | ||
| 607 | |||
| 608 | result = ps3_irq_plug_destroy(virq); | ||
| 518 | BUG_ON(result); | 609 | BUG_ON(result); |
| 519 | return 0; | 610 | |
| 611 | return result; | ||
| 520 | } | 612 | } |
| 521 | 613 | ||
| 522 | 614 | ||
| @@ -533,7 +625,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, | |||
| 533 | *p & 0xffff); | 625 | *p & 0xffff); |
| 534 | } | 626 | } |
| 535 | 627 | ||
| 536 | static void __attribute__ ((unused)) _dump_256_bmp(const char *header, | 628 | static void __maybe_unused _dump_256_bmp(const char *header, |
| 537 | const u64 *p, unsigned cpu, const char* func, int line) | 629 | const u64 *p, unsigned cpu, const char* func, int line) |
| 538 | { | 630 | { |
| 539 | pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", | 631 | pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", |
| @@ -546,86 +638,25 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line) | |||
| 546 | unsigned long flags; | 638 | unsigned long flags; |
| 547 | 639 | ||
| 548 | spin_lock_irqsave(&pd->bmp.lock, flags); | 640 | spin_lock_irqsave(&pd->bmp.lock, flags); |
| 549 | _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line); | 641 | _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line); |
| 550 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | 642 | _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); |
| 551 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | 643 | spin_unlock_irqrestore(&pd->bmp.lock, flags); |
| 552 | } | 644 | } |
| 553 | 645 | ||
| 554 | #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) | 646 | #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) |
| 555 | static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd, | 647 | static void __maybe_unused _dump_mask(struct ps3_private *pd, |
| 556 | const char* func, int line) | 648 | const char* func, int line) |
| 557 | { | 649 | { |
| 558 | unsigned long flags; | 650 | unsigned long flags; |
| 559 | 651 | ||
| 560 | spin_lock_irqsave(&pd->bmp.lock, flags); | 652 | spin_lock_irqsave(&pd->bmp.lock, flags); |
| 561 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | 653 | _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); |
| 562 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | 654 | spin_unlock_irqrestore(&pd->bmp.lock, flags); |
| 563 | } | 655 | } |
| 564 | #else | 656 | #else |
| 565 | static void dump_bmp(struct ps3_private* pd) {}; | 657 | static void dump_bmp(struct ps3_private* pd) {}; |
| 566 | #endif /* defined(DEBUG) */ | 658 | #endif /* defined(DEBUG) */ |
| 567 | 659 | ||
| 568 | static void ps3_chip_mask(unsigned int virq) | ||
| 569 | { | ||
| 570 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 571 | u64 bit = 0x8000000000000000UL >> virq; | ||
| 572 | u64 *p = &pd->bmp.mask; | ||
| 573 | u64 old; | ||
| 574 | unsigned long flags; | ||
| 575 | |||
| 576 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
| 577 | |||
| 578 | local_irq_save(flags); | ||
| 579 | asm volatile( | ||
| 580 | "1: ldarx %0,0,%3\n" | ||
| 581 | "andc %0,%0,%2\n" | ||
| 582 | "stdcx. %0,0,%3\n" | ||
| 583 | "bne- 1b" | ||
| 584 | : "=&r" (old), "+m" (*p) | ||
| 585 | : "r" (bit), "r" (p) | ||
| 586 | : "cc" ); | ||
| 587 | |||
| 588 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
| 589 | local_irq_restore(flags); | ||
| 590 | } | ||
| 591 | |||
| 592 | static void ps3_chip_unmask(unsigned int virq) | ||
| 593 | { | ||
| 594 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 595 | u64 bit = 0x8000000000000000UL >> virq; | ||
| 596 | u64 *p = &pd->bmp.mask; | ||
| 597 | u64 old; | ||
| 598 | unsigned long flags; | ||
| 599 | |||
| 600 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
| 601 | |||
| 602 | local_irq_save(flags); | ||
| 603 | asm volatile( | ||
| 604 | "1: ldarx %0,0,%3\n" | ||
| 605 | "or %0,%0,%2\n" | ||
| 606 | "stdcx. %0,0,%3\n" | ||
| 607 | "bne- 1b" | ||
| 608 | : "=&r" (old), "+m" (*p) | ||
| 609 | : "r" (bit), "r" (p) | ||
| 610 | : "cc" ); | ||
| 611 | |||
| 612 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
| 613 | local_irq_restore(flags); | ||
| 614 | } | ||
| 615 | |||
| 616 | static void ps3_chip_eoi(unsigned int virq) | ||
| 617 | { | ||
| 618 | const struct ps3_private *pd = get_irq_chip_data(virq); | ||
| 619 | lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq); | ||
| 620 | } | ||
| 621 | |||
| 622 | static struct irq_chip irq_chip = { | ||
| 623 | .typename = "ps3", | ||
| 624 | .mask = ps3_chip_mask, | ||
| 625 | .unmask = ps3_chip_unmask, | ||
| 626 | .eoi = ps3_chip_eoi, | ||
| 627 | }; | ||
| 628 | |||
| 629 | static void ps3_host_unmap(struct irq_host *h, unsigned int virq) | 660 | static void ps3_host_unmap(struct irq_host *h, unsigned int virq) |
| 630 | { | 661 | { |
| 631 | set_irq_chip_data(virq, NULL); | 662 | set_irq_chip_data(virq, NULL); |
| @@ -637,7 +668,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, | |||
| 637 | pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, | 668 | pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, |
| 638 | virq); | 669 | virq); |
| 639 | 670 | ||
| 640 | set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); | 671 | set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq); |
| 641 | 672 | ||
| 642 | return 0; | 673 | return 0; |
| 643 | } | 674 | } |
| @@ -657,7 +688,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) | |||
| 657 | cpu, virq, pd->bmp.ipi_debug_brk_mask); | 688 | cpu, virq, pd->bmp.ipi_debug_brk_mask); |
| 658 | } | 689 | } |
| 659 | 690 | ||
| 660 | unsigned int ps3_get_irq(void) | 691 | static unsigned int ps3_get_irq(void) |
| 661 | { | 692 | { |
| 662 | struct ps3_private *pd = &__get_cpu_var(ps3_private); | 693 | struct ps3_private *pd = &__get_cpu_var(ps3_private); |
| 663 | u64 x = (pd->bmp.status & pd->bmp.mask); | 694 | u64 x = (pd->bmp.status & pd->bmp.mask); |
| @@ -672,8 +703,8 @@ unsigned int ps3_get_irq(void) | |||
| 672 | plug &= 0x3f; | 703 | plug &= 0x3f; |
| 673 | 704 | ||
| 674 | if (unlikely(plug) == NO_IRQ) { | 705 | if (unlikely(plug) == NO_IRQ) { |
| 675 | pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__, | 706 | pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__, |
| 676 | pd->cpu); | 707 | __LINE__, pd->thread_id); |
| 677 | dump_bmp(&per_cpu(ps3_private, 0)); | 708 | dump_bmp(&per_cpu(ps3_private, 0)); |
| 678 | dump_bmp(&per_cpu(ps3_private, 1)); | 709 | dump_bmp(&per_cpu(ps3_private, 1)); |
| 679 | return NO_IRQ; | 710 | return NO_IRQ; |
| @@ -703,16 +734,16 @@ void __init ps3_init_IRQ(void) | |||
| 703 | for_each_possible_cpu(cpu) { | 734 | for_each_possible_cpu(cpu) { |
| 704 | struct ps3_private *pd = &per_cpu(ps3_private, cpu); | 735 | struct ps3_private *pd = &per_cpu(ps3_private, cpu); |
| 705 | 736 | ||
| 706 | lv1_get_logical_ppe_id(&pd->node); | 737 | lv1_get_logical_ppe_id(&pd->ppe_id); |
| 707 | pd->cpu = get_hard_smp_processor_id(cpu); | 738 | pd->thread_id = get_hard_smp_processor_id(cpu); |
| 708 | spin_lock_init(&pd->bmp.lock); | 739 | spin_lock_init(&pd->bmp.lock); |
| 709 | 740 | ||
| 710 | pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__, | 741 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n", |
| 711 | __LINE__, pd->node, pd->cpu, | 742 | __func__, __LINE__, pd->ppe_id, pd->thread_id, |
| 712 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); | 743 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); |
| 713 | 744 | ||
| 714 | result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu, | 745 | result = lv1_configure_irq_state_bitmap(pd->ppe_id, |
| 715 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); | 746 | pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); |
| 716 | 747 | ||
| 717 | if (result) | 748 | if (result) |
| 718 | pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" | 749 | pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" |
| @@ -722,3 +753,16 @@ void __init ps3_init_IRQ(void) | |||
| 722 | 753 | ||
| 723 | ppc_md.get_irq = ps3_get_irq; | 754 | ppc_md.get_irq = ps3_get_irq; |
| 724 | } | 755 | } |
| 756 | |||
| 757 | void ps3_shutdown_IRQ(int cpu) | ||
| 758 | { | ||
| 759 | int result; | ||
| 760 | u64 ppe_id; | ||
| 761 | u64 thread_id = get_hard_smp_processor_id(cpu); | ||
| 762 | |||
| 763 | lv1_get_logical_ppe_id(&ppe_id); | ||
| 764 | result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0); | ||
| 765 | |||
| 766 | DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__, | ||
| 767 | __LINE__, ppe_id, thread_id, cpu, ps3_result(result)); | ||
| 768 | } | ||
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index f8a3e206c584..7bb3e1620974 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c | |||
| @@ -30,9 +30,9 @@ | |||
| 30 | #include "platform.h" | 30 | #include "platform.h" |
| 31 | 31 | ||
| 32 | #if defined(DEBUG) | 32 | #if defined(DEBUG) |
| 33 | #define DBG(fmt...) udbg_printf(fmt) | 33 | #define DBG udbg_printf |
| 34 | #else | 34 | #else |
| 35 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 35 | #define DBG pr_debug |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | enum { | 38 | enum { |
| @@ -115,7 +115,8 @@ struct map { | |||
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) | 117 | #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) |
| 118 | static void _debug_dump_map(const struct map* m, const char* func, int line) | 118 | static void __maybe_unused _debug_dump_map(const struct map *m, |
| 119 | const char *func, int line) | ||
| 119 | { | 120 | { |
| 120 | DBG("%s:%d: map.total = %lxh\n", func, line, m->total); | 121 | DBG("%s:%d: map.total = %lxh\n", func, line, m->total); |
| 121 | DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); | 122 | DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); |
| @@ -212,9 +213,15 @@ fail: | |||
| 212 | 213 | ||
| 213 | void ps3_mm_vas_destroy(void) | 214 | void ps3_mm_vas_destroy(void) |
| 214 | { | 215 | { |
| 216 | int result; | ||
| 217 | |||
| 218 | DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id); | ||
| 219 | |||
| 215 | if (map.vas_id) { | 220 | if (map.vas_id) { |
| 216 | lv1_select_virtual_address_space(0); | 221 | result = lv1_select_virtual_address_space(0); |
| 217 | lv1_destruct_virtual_address_space(map.vas_id); | 222 | BUG_ON(result); |
| 223 | result = lv1_destruct_virtual_address_space(map.vas_id); | ||
| 224 | BUG_ON(result); | ||
| 218 | map.vas_id = 0; | 225 | map.vas_id = 0; |
| 219 | } | 226 | } |
| 220 | } | 227 | } |
| @@ -232,7 +239,7 @@ void ps3_mm_vas_destroy(void) | |||
| 232 | * @size is rounded down to a multiple of the vas large page size. | 239 | * @size is rounded down to a multiple of the vas large page size. |
| 233 | */ | 240 | */ |
| 234 | 241 | ||
| 235 | int ps3_mm_region_create(struct mem_region *r, unsigned long size) | 242 | static int ps3_mm_region_create(struct mem_region *r, unsigned long size) |
| 236 | { | 243 | { |
| 237 | int result; | 244 | int result; |
| 238 | unsigned long muid; | 245 | unsigned long muid; |
| @@ -273,10 +280,14 @@ zero_region: | |||
| 273 | * @r: pointer to struct mem_region | 280 | * @r: pointer to struct mem_region |
| 274 | */ | 281 | */ |
| 275 | 282 | ||
| 276 | void ps3_mm_region_destroy(struct mem_region *r) | 283 | static void ps3_mm_region_destroy(struct mem_region *r) |
| 277 | { | 284 | { |
| 285 | int result; | ||
| 286 | |||
| 287 | DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base); | ||
| 278 | if (r->base) { | 288 | if (r->base) { |
| 279 | lv1_release_memory(r->base); | 289 | result = lv1_release_memory(r->base); |
| 290 | BUG_ON(result); | ||
| 280 | r->size = r->base = r->offset = 0; | 291 | r->size = r->base = r->offset = 0; |
| 281 | map.total = map.rm.size; | 292 | map.total = map.rm.size; |
| 282 | } | 293 | } |
| @@ -329,31 +340,34 @@ core_initcall(ps3_mm_add_memory); | |||
| 329 | /*============================================================================*/ | 340 | /*============================================================================*/ |
| 330 | 341 | ||
| 331 | /** | 342 | /** |
| 332 | * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address. | 343 | * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address. |
| 333 | * @r: pointer to dma region structure | 344 | * @r: pointer to dma region structure |
| 334 | * @lpar_addr: HV lpar address | 345 | * @lpar_addr: HV lpar address |
| 335 | */ | 346 | */ |
| 336 | 347 | ||
| 337 | static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r, | 348 | static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r, |
| 338 | unsigned long lpar_addr) | 349 | unsigned long lpar_addr) |
| 339 | { | 350 | { |
| 340 | BUG_ON(lpar_addr >= map.r1.base + map.r1.size); | 351 | if (lpar_addr >= map.rm.size) |
| 341 | return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr | 352 | lpar_addr -= map.r1.offset; |
| 342 | : lpar_addr - map.r1.offset); | 353 | BUG_ON(lpar_addr < r->offset); |
| 354 | BUG_ON(lpar_addr >= r->offset + r->len); | ||
| 355 | return r->bus_addr + lpar_addr - r->offset; | ||
| 343 | } | 356 | } |
| 344 | 357 | ||
| 345 | #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) | 358 | #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) |
| 346 | static void _dma_dump_region(const struct ps3_dma_region *r, const char* func, | 359 | static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, |
| 347 | int line) | 360 | const char *func, int line) |
| 348 | { | 361 | { |
| 349 | DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | 362 | DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, |
| 350 | r->did.dev_id); | 363 | r->dev->dev_id); |
| 351 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); | 364 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); |
| 352 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 365 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
| 353 | DBG("%s:%d: len %lxh\n", func, line, r->len); | 366 | DBG("%s:%d: len %lxh\n", func, line, r->len); |
| 367 | DBG("%s:%d: offset %lxh\n", func, line, r->offset); | ||
| 354 | } | 368 | } |
| 355 | 369 | ||
| 356 | /** | 370 | /** |
| 357 | * dma_chunk - A chunk of dma pages mapped by the io controller. | 371 | * dma_chunk - A chunk of dma pages mapped by the io controller. |
| 358 | * @region - The dma region that owns this chunk. | 372 | * @region - The dma region that owns this chunk. |
| 359 | * @lpar_addr: Starting lpar address of the area to map. | 373 | * @lpar_addr: Starting lpar address of the area to map. |
| @@ -381,10 +395,11 @@ static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, | |||
| 381 | int line) | 395 | int line) |
| 382 | { | 396 | { |
| 383 | DBG("%s:%d: r.dev %u:%u\n", func, line, | 397 | DBG("%s:%d: r.dev %u:%u\n", func, line, |
| 384 | c->region->did.bus_id, c->region->did.dev_id); | 398 | c->region->dev->bus_id, c->region->dev->dev_id); |
| 385 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); | 399 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); |
| 386 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); | 400 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); |
| 387 | DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); | 401 | DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); |
| 402 | DBG("%s:%d: r.offset %lxh\n", func, line, c->region->offset); | ||
| 388 | DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); | 403 | DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); |
| 389 | DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); | 404 | DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); |
| 390 | DBG("%s:%d: c.len %lxh\n", func, line, c->len); | 405 | DBG("%s:%d: c.len %lxh\n", func, line, c->len); |
| @@ -395,39 +410,68 @@ static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r, | |||
| 395 | { | 410 | { |
| 396 | struct dma_chunk *c; | 411 | struct dma_chunk *c; |
| 397 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); | 412 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); |
| 398 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | 413 | unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus, |
| 414 | 1 << r->page_size); | ||
| 399 | 415 | ||
| 400 | list_for_each_entry(c, &r->chunk_list.head, link) { | 416 | list_for_each_entry(c, &r->chunk_list.head, link) { |
| 401 | /* intersection */ | 417 | /* intersection */ |
| 402 | if (aligned_bus >= c->bus_addr | 418 | if (aligned_bus >= c->bus_addr && |
| 403 | && aligned_bus < c->bus_addr + c->len | 419 | aligned_bus + aligned_len <= c->bus_addr + c->len) |
| 404 | && aligned_bus + aligned_len <= c->bus_addr + c->len) { | ||
| 405 | return c; | 420 | return c; |
| 406 | } | 421 | |
| 407 | /* below */ | 422 | /* below */ |
| 408 | if (aligned_bus + aligned_len <= c->bus_addr) { | 423 | if (aligned_bus + aligned_len <= c->bus_addr) |
| 409 | continue; | 424 | continue; |
| 410 | } | 425 | |
| 411 | /* above */ | 426 | /* above */ |
| 412 | if (aligned_bus >= c->bus_addr + c->len) { | 427 | if (aligned_bus >= c->bus_addr + c->len) |
| 413 | continue; | 428 | continue; |
| 414 | } | ||
| 415 | 429 | ||
| 416 | /* we don't handle the multi-chunk case for now */ | 430 | /* we don't handle the multi-chunk case for now */ |
| 417 | |||
| 418 | dma_dump_chunk(c); | 431 | dma_dump_chunk(c); |
| 419 | BUG(); | 432 | BUG(); |
| 420 | } | 433 | } |
| 421 | return NULL; | 434 | return NULL; |
| 422 | } | 435 | } |
| 423 | 436 | ||
| 424 | static int dma_free_chunk(struct dma_chunk *c) | 437 | static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r, |
| 438 | unsigned long lpar_addr, unsigned long len) | ||
| 439 | { | ||
| 440 | struct dma_chunk *c; | ||
| 441 | unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size); | ||
| 442 | unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar, | ||
| 443 | 1 << r->page_size); | ||
| 444 | |||
| 445 | list_for_each_entry(c, &r->chunk_list.head, link) { | ||
| 446 | /* intersection */ | ||
| 447 | if (c->lpar_addr <= aligned_lpar && | ||
| 448 | aligned_lpar < c->lpar_addr + c->len) { | ||
| 449 | if (aligned_lpar + aligned_len <= c->lpar_addr + c->len) | ||
| 450 | return c; | ||
| 451 | else { | ||
| 452 | dma_dump_chunk(c); | ||
| 453 | BUG(); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | /* below */ | ||
| 457 | if (aligned_lpar + aligned_len <= c->lpar_addr) { | ||
| 458 | continue; | ||
| 459 | } | ||
| 460 | /* above */ | ||
| 461 | if (c->lpar_addr + c->len <= aligned_lpar) { | ||
| 462 | continue; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | return NULL; | ||
| 466 | } | ||
| 467 | |||
| 468 | static int dma_sb_free_chunk(struct dma_chunk *c) | ||
| 425 | { | 469 | { |
| 426 | int result = 0; | 470 | int result = 0; |
| 427 | 471 | ||
| 428 | if (c->bus_addr) { | 472 | if (c->bus_addr) { |
| 429 | result = lv1_unmap_device_dma_region(c->region->did.bus_id, | 473 | result = lv1_unmap_device_dma_region(c->region->dev->bus_id, |
| 430 | c->region->did.dev_id, c->bus_addr, c->len); | 474 | c->region->dev->dev_id, c->bus_addr, c->len); |
| 431 | BUG_ON(result); | 475 | BUG_ON(result); |
| 432 | } | 476 | } |
| 433 | 477 | ||
| @@ -435,8 +479,39 @@ static int dma_free_chunk(struct dma_chunk *c) | |||
| 435 | return result; | 479 | return result; |
| 436 | } | 480 | } |
| 437 | 481 | ||
| 482 | static int dma_ioc0_free_chunk(struct dma_chunk *c) | ||
| 483 | { | ||
| 484 | int result = 0; | ||
| 485 | int iopage; | ||
| 486 | unsigned long offset; | ||
| 487 | struct ps3_dma_region *r = c->region; | ||
| 488 | |||
| 489 | DBG("%s:start\n", __func__); | ||
| 490 | for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) { | ||
| 491 | offset = (1 << r->page_size) * iopage; | ||
| 492 | /* put INVALID entry */ | ||
| 493 | result = lv1_put_iopte(0, | ||
| 494 | c->bus_addr + offset, | ||
| 495 | c->lpar_addr + offset, | ||
| 496 | r->ioid, | ||
| 497 | 0); | ||
| 498 | DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__, | ||
| 499 | c->bus_addr + offset, | ||
| 500 | c->lpar_addr + offset, | ||
| 501 | r->ioid); | ||
| 502 | |||
| 503 | if (result) { | ||
| 504 | DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__, | ||
| 505 | __LINE__, ps3_result(result)); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | kfree(c); | ||
| 509 | DBG("%s:end\n", __func__); | ||
| 510 | return result; | ||
| 511 | } | ||
| 512 | |||
| 438 | /** | 513 | /** |
| 439 | * dma_map_pages - Maps dma pages into the io controller bus address space. | 514 | * dma_sb_map_pages - Maps dma pages into the io controller bus address space. |
| 440 | * @r: Pointer to a struct ps3_dma_region. | 515 | * @r: Pointer to a struct ps3_dma_region. |
| 441 | * @phys_addr: Starting physical address of the area to map. | 516 | * @phys_addr: Starting physical address of the area to map. |
| 442 | * @len: Length in bytes of the area to map. | 517 | * @len: Length in bytes of the area to map. |
| @@ -446,8 +521,8 @@ static int dma_free_chunk(struct dma_chunk *c) | |||
| 446 | * make the HV call to add the pages into the io controller address space. | 521 | * make the HV call to add the pages into the io controller address space. |
| 447 | */ | 522 | */ |
| 448 | 523 | ||
| 449 | static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | 524 | static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, |
| 450 | unsigned long len, struct dma_chunk **c_out) | 525 | unsigned long len, struct dma_chunk **c_out, u64 iopte_flag) |
| 451 | { | 526 | { |
| 452 | int result; | 527 | int result; |
| 453 | struct dma_chunk *c; | 528 | struct dma_chunk *c; |
| @@ -461,13 +536,13 @@ static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | |||
| 461 | 536 | ||
| 462 | c->region = r; | 537 | c->region = r; |
| 463 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | 538 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); |
| 464 | c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr); | 539 | c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr); |
| 465 | c->len = len; | 540 | c->len = len; |
| 466 | 541 | ||
| 467 | result = lv1_map_device_dma_region(c->region->did.bus_id, | 542 | BUG_ON(iopte_flag != 0xf800000000000000UL); |
| 468 | c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len, | 543 | result = lv1_map_device_dma_region(c->region->dev->bus_id, |
| 469 | 0xf800000000000000UL); | 544 | c->region->dev->dev_id, c->lpar_addr, |
| 470 | 545 | c->bus_addr, c->len, iopte_flag); | |
| 471 | if (result) { | 546 | if (result) { |
| 472 | DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", | 547 | DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", |
| 473 | __func__, __LINE__, ps3_result(result)); | 548 | __func__, __LINE__, ps3_result(result)); |
| @@ -487,26 +562,120 @@ fail_alloc: | |||
| 487 | return result; | 562 | return result; |
| 488 | } | 563 | } |
| 489 | 564 | ||
| 565 | static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | ||
| 566 | unsigned long len, struct dma_chunk **c_out, | ||
| 567 | u64 iopte_flag) | ||
| 568 | { | ||
| 569 | int result; | ||
| 570 | struct dma_chunk *c, *last; | ||
| 571 | int iopage, pages; | ||
| 572 | unsigned long offset; | ||
| 573 | |||
| 574 | DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__, | ||
| 575 | phys_addr, ps3_mm_phys_to_lpar(phys_addr), len); | ||
| 576 | c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); | ||
| 577 | |||
| 578 | if (!c) { | ||
| 579 | result = -ENOMEM; | ||
| 580 | goto fail_alloc; | ||
| 581 | } | ||
| 582 | |||
| 583 | c->region = r; | ||
| 584 | c->len = len; | ||
| 585 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | ||
| 586 | /* allocate IO address */ | ||
| 587 | if (list_empty(&r->chunk_list.head)) { | ||
| 588 | /* first one */ | ||
| 589 | c->bus_addr = r->bus_addr; | ||
| 590 | } else { | ||
| 591 | /* derive from last bus addr*/ | ||
| 592 | last = list_entry(r->chunk_list.head.next, | ||
| 593 | struct dma_chunk, link); | ||
| 594 | c->bus_addr = last->bus_addr + last->len; | ||
| 595 | DBG("%s: last bus=%#lx, len=%#lx\n", __func__, | ||
| 596 | last->bus_addr, last->len); | ||
| 597 | } | ||
| 598 | |||
| 599 | /* FIXME: check whether length exceeds region size */ | ||
| 600 | |||
| 601 | /* build ioptes for the area */ | ||
| 602 | pages = len >> r->page_size; | ||
| 603 | DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__, | ||
| 604 | r->page_size, r->len, pages, iopte_flag); | ||
| 605 | for (iopage = 0; iopage < pages; iopage++) { | ||
| 606 | offset = (1 << r->page_size) * iopage; | ||
| 607 | result = lv1_put_iopte(0, | ||
| 608 | c->bus_addr + offset, | ||
| 609 | c->lpar_addr + offset, | ||
| 610 | r->ioid, | ||
| 611 | iopte_flag); | ||
| 612 | if (result) { | ||
| 613 | printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region " | ||
| 614 | "failed: %s\n", __func__, __LINE__, | ||
| 615 | ps3_result(result)); | ||
| 616 | goto fail_map; | ||
| 617 | } | ||
| 618 | DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__, | ||
| 619 | iopage, c->bus_addr + offset, c->lpar_addr + offset, | ||
| 620 | r->ioid); | ||
| 621 | } | ||
| 622 | |||
| 623 | /* be sure that last allocated one is inserted at head */ | ||
| 624 | list_add(&c->link, &r->chunk_list.head); | ||
| 625 | |||
| 626 | *c_out = c; | ||
| 627 | DBG("%s: end\n", __func__); | ||
| 628 | return 0; | ||
| 629 | |||
| 630 | fail_map: | ||
| 631 | for (iopage--; 0 <= iopage; iopage--) { | ||
| 632 | lv1_put_iopte(0, | ||
| 633 | c->bus_addr + offset, | ||
| 634 | c->lpar_addr + offset, | ||
| 635 | r->ioid, | ||
| 636 | 0); | ||
| 637 | } | ||
| 638 | kfree(c); | ||
| 639 | fail_alloc: | ||
| 640 | *c_out = NULL; | ||
| 641 | return result; | ||
| 642 | } | ||
| 643 | |||
| 490 | /** | 644 | /** |
| 491 | * dma_region_create - Create a device dma region. | 645 | * dma_sb_region_create - Create a device dma region. |
| 492 | * @r: Pointer to a struct ps3_dma_region. | 646 | * @r: Pointer to a struct ps3_dma_region. |
| 493 | * | 647 | * |
| 494 | * This is the lowest level dma region create routine, and is the one that | 648 | * This is the lowest level dma region create routine, and is the one that |
| 495 | * will make the HV call to create the region. | 649 | * will make the HV call to create the region. |
| 496 | */ | 650 | */ |
| 497 | 651 | ||
| 498 | static int dma_region_create(struct ps3_dma_region* r) | 652 | static int dma_sb_region_create(struct ps3_dma_region *r) |
| 499 | { | 653 | { |
| 500 | int result; | 654 | int result; |
| 501 | 655 | ||
| 502 | r->len = _ALIGN_UP(map.total, 1 << r->page_size); | 656 | pr_info(" -> %s:%d:\n", __func__, __LINE__); |
| 657 | |||
| 658 | BUG_ON(!r); | ||
| 659 | |||
| 660 | if (!r->dev->bus_id) { | ||
| 661 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | ||
| 662 | r->dev->bus_id, r->dev->dev_id); | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__, | ||
| 667 | __LINE__, r->len, r->page_size, r->offset); | ||
| 668 | |||
| 669 | BUG_ON(!r->len); | ||
| 670 | BUG_ON(!r->page_size); | ||
| 671 | BUG_ON(!r->region_ops); | ||
| 672 | |||
| 503 | INIT_LIST_HEAD(&r->chunk_list.head); | 673 | INIT_LIST_HEAD(&r->chunk_list.head); |
| 504 | spin_lock_init(&r->chunk_list.lock); | 674 | spin_lock_init(&r->chunk_list.lock); |
| 505 | 675 | ||
| 506 | result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id, | 676 | result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id, |
| 507 | r->len, r->page_size, r->region_type, &r->bus_addr); | 677 | roundup_pow_of_two(r->len), r->page_size, r->region_type, |
| 508 | 678 | &r->bus_addr); | |
| 509 | dma_dump_region(r); | ||
| 510 | 679 | ||
| 511 | if (result) { | 680 | if (result) { |
| 512 | DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", | 681 | DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", |
| @@ -517,6 +686,27 @@ static int dma_region_create(struct ps3_dma_region* r) | |||
| 517 | return result; | 686 | return result; |
| 518 | } | 687 | } |
| 519 | 688 | ||
| 689 | static int dma_ioc0_region_create(struct ps3_dma_region *r) | ||
| 690 | { | ||
| 691 | int result; | ||
| 692 | |||
| 693 | INIT_LIST_HEAD(&r->chunk_list.head); | ||
| 694 | spin_lock_init(&r->chunk_list.lock); | ||
| 695 | |||
| 696 | result = lv1_allocate_io_segment(0, | ||
| 697 | r->len, | ||
| 698 | r->page_size, | ||
| 699 | &r->bus_addr); | ||
| 700 | if (result) { | ||
| 701 | DBG("%s:%d: lv1_allocate_io_segment failed: %s\n", | ||
| 702 | __func__, __LINE__, ps3_result(result)); | ||
| 703 | r->len = r->bus_addr = 0; | ||
| 704 | } | ||
| 705 | DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__, | ||
| 706 | r->len, r->page_size, r->bus_addr); | ||
| 707 | return result; | ||
| 708 | } | ||
| 709 | |||
| 520 | /** | 710 | /** |
| 521 | * dma_region_free - Free a device dma region. | 711 | * dma_region_free - Free a device dma region. |
| 522 | * @r: Pointer to a struct ps3_dma_region. | 712 | * @r: Pointer to a struct ps3_dma_region. |
| @@ -525,31 +715,62 @@ static int dma_region_create(struct ps3_dma_region* r) | |||
| 525 | * will make the HV call to free the region. | 715 | * will make the HV call to free the region. |
| 526 | */ | 716 | */ |
| 527 | 717 | ||
| 528 | static int dma_region_free(struct ps3_dma_region* r) | 718 | static int dma_sb_region_free(struct ps3_dma_region *r) |
| 529 | { | 719 | { |
| 530 | int result; | 720 | int result; |
| 531 | struct dma_chunk *c; | 721 | struct dma_chunk *c; |
| 532 | struct dma_chunk *tmp; | 722 | struct dma_chunk *tmp; |
| 533 | 723 | ||
| 724 | BUG_ON(!r); | ||
| 725 | |||
| 726 | if (!r->dev->bus_id) { | ||
| 727 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | ||
| 728 | r->dev->bus_id, r->dev->dev_id); | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 534 | list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { | 732 | list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { |
| 535 | list_del(&c->link); | 733 | list_del(&c->link); |
| 536 | dma_free_chunk(c); | 734 | dma_sb_free_chunk(c); |
| 537 | } | 735 | } |
| 538 | 736 | ||
| 539 | result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id, | 737 | result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id, |
| 540 | r->bus_addr); | 738 | r->bus_addr); |
| 541 | 739 | ||
| 542 | if (result) | 740 | if (result) |
| 543 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", | 741 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", |
| 544 | __func__, __LINE__, ps3_result(result)); | 742 | __func__, __LINE__, ps3_result(result)); |
| 545 | 743 | ||
| 546 | r->len = r->bus_addr = 0; | 744 | r->bus_addr = 0; |
| 745 | |||
| 746 | return result; | ||
| 747 | } | ||
| 748 | |||
| 749 | static int dma_ioc0_region_free(struct ps3_dma_region *r) | ||
| 750 | { | ||
| 751 | int result; | ||
| 752 | struct dma_chunk *c, *n; | ||
| 753 | |||
| 754 | DBG("%s: start\n", __func__); | ||
| 755 | list_for_each_entry_safe(c, n, &r->chunk_list.head, link) { | ||
| 756 | list_del(&c->link); | ||
| 757 | dma_ioc0_free_chunk(c); | ||
| 758 | } | ||
| 759 | |||
| 760 | result = lv1_release_io_segment(0, r->bus_addr); | ||
| 761 | |||
| 762 | if (result) | ||
| 763 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", | ||
| 764 | __func__, __LINE__, ps3_result(result)); | ||
| 765 | |||
| 766 | r->bus_addr = 0; | ||
| 767 | DBG("%s: end\n", __func__); | ||
| 547 | 768 | ||
| 548 | return result; | 769 | return result; |
| 549 | } | 770 | } |
| 550 | 771 | ||
| 551 | /** | 772 | /** |
| 552 | * dma_map_area - Map an area of memory into a device dma region. | 773 | * dma_sb_map_area - Map an area of memory into a device dma region. |
| 553 | * @r: Pointer to a struct ps3_dma_region. | 774 | * @r: Pointer to a struct ps3_dma_region. |
| 554 | * @virt_addr: Starting virtual address of the area to map. | 775 | * @virt_addr: Starting virtual address of the area to map. |
| 555 | * @len: Length in bytes of the area to map. | 776 | * @len: Length in bytes of the area to map. |
| @@ -559,16 +780,19 @@ static int dma_region_free(struct ps3_dma_region* r) | |||
| 559 | * This is the common dma mapping routine. | 780 | * This is the common dma mapping routine. |
| 560 | */ | 781 | */ |
| 561 | 782 | ||
| 562 | static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | 783 | static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr, |
| 563 | unsigned long len, unsigned long *bus_addr) | 784 | unsigned long len, unsigned long *bus_addr, |
| 785 | u64 iopte_flag) | ||
| 564 | { | 786 | { |
| 565 | int result; | 787 | int result; |
| 566 | unsigned long flags; | 788 | unsigned long flags; |
| 567 | struct dma_chunk *c; | 789 | struct dma_chunk *c; |
| 568 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | 790 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) |
| 569 | : virt_addr; | 791 | : virt_addr; |
| 570 | 792 | unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); | |
| 571 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | 793 | unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, |
| 794 | 1 << r->page_size); | ||
| 795 | *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | ||
| 572 | 796 | ||
| 573 | if (!USE_DYNAMIC_DMA) { | 797 | if (!USE_DYNAMIC_DMA) { |
| 574 | unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | 798 | unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); |
| @@ -588,17 +812,18 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
| 588 | c = dma_find_chunk(r, *bus_addr, len); | 812 | c = dma_find_chunk(r, *bus_addr, len); |
| 589 | 813 | ||
| 590 | if (c) { | 814 | if (c) { |
| 815 | DBG("%s:%d: reusing mapped chunk", __func__, __LINE__); | ||
| 816 | dma_dump_chunk(c); | ||
| 591 | c->usage_count++; | 817 | c->usage_count++; |
| 592 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 818 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
| 593 | return 0; | 819 | return 0; |
| 594 | } | 820 | } |
| 595 | 821 | ||
| 596 | result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size), | 822 | result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag); |
| 597 | _ALIGN_UP(len, 1 << r->page_size), &c); | ||
| 598 | 823 | ||
| 599 | if (result) { | 824 | if (result) { |
| 600 | *bus_addr = 0; | 825 | *bus_addr = 0; |
| 601 | DBG("%s:%d: dma_map_pages failed (%d)\n", | 826 | DBG("%s:%d: dma_sb_map_pages failed (%d)\n", |
| 602 | __func__, __LINE__, result); | 827 | __func__, __LINE__, result); |
| 603 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 828 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
| 604 | return result; | 829 | return result; |
| @@ -610,8 +835,57 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
| 610 | return result; | 835 | return result; |
| 611 | } | 836 | } |
| 612 | 837 | ||
| 838 | static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | ||
| 839 | unsigned long len, unsigned long *bus_addr, | ||
| 840 | u64 iopte_flag) | ||
| 841 | { | ||
| 842 | int result; | ||
| 843 | unsigned long flags; | ||
| 844 | struct dma_chunk *c; | ||
| 845 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | ||
| 846 | : virt_addr; | ||
| 847 | unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); | ||
| 848 | unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, | ||
| 849 | 1 << r->page_size); | ||
| 850 | |||
| 851 | DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__, | ||
| 852 | virt_addr, len); | ||
| 853 | DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__, | ||
| 854 | phys_addr, aligned_phys, aligned_len); | ||
| 855 | |||
| 856 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
| 857 | c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len); | ||
| 858 | |||
| 859 | if (c) { | ||
| 860 | /* FIXME */ | ||
| 861 | BUG(); | ||
| 862 | *bus_addr = c->bus_addr + phys_addr - aligned_phys; | ||
| 863 | c->usage_count++; | ||
| 864 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
| 865 | return 0; | ||
| 866 | } | ||
| 867 | |||
| 868 | result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c, | ||
| 869 | iopte_flag); | ||
| 870 | |||
| 871 | if (result) { | ||
| 872 | *bus_addr = 0; | ||
| 873 | DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n", | ||
| 874 | __func__, __LINE__, result); | ||
| 875 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
| 876 | return result; | ||
| 877 | } | ||
| 878 | *bus_addr = c->bus_addr + phys_addr - aligned_phys; | ||
| 879 | DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__, | ||
| 880 | virt_addr, phys_addr, aligned_phys, *bus_addr); | ||
| 881 | c->usage_count = 1; | ||
| 882 | |||
| 883 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
| 884 | return result; | ||
| 885 | } | ||
| 886 | |||
| 613 | /** | 887 | /** |
| 614 | * dma_unmap_area - Unmap an area of memory from a device dma region. | 888 | * dma_sb_unmap_area - Unmap an area of memory from a device dma region. |
| 615 | * @r: Pointer to a struct ps3_dma_region. | 889 | * @r: Pointer to a struct ps3_dma_region. |
| 616 | * @bus_addr: The starting ioc bus address of the area to unmap. | 890 | * @bus_addr: The starting ioc bus address of the area to unmap. |
| 617 | * @len: Length in bytes of the area to unmap. | 891 | * @len: Length in bytes of the area to unmap. |
| @@ -619,7 +893,7 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
| 619 | * This is the common dma unmap routine. | 893 | * This is the common dma unmap routine. |
| 620 | */ | 894 | */ |
| 621 | 895 | ||
| 622 | int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | 896 | static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, |
| 623 | unsigned long len) | 897 | unsigned long len) |
| 624 | { | 898 | { |
| 625 | unsigned long flags; | 899 | unsigned long flags; |
| @@ -631,7 +905,8 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | |||
| 631 | if (!c) { | 905 | if (!c) { |
| 632 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, | 906 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, |
| 633 | 1 << r->page_size); | 907 | 1 << r->page_size); |
| 634 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | 908 | unsigned long aligned_len = _ALIGN_UP(len + bus_addr |
| 909 | - aligned_bus, 1 << r->page_size); | ||
| 635 | DBG("%s:%d: not found: bus_addr %lxh\n", | 910 | DBG("%s:%d: not found: bus_addr %lxh\n", |
| 636 | __func__, __LINE__, bus_addr); | 911 | __func__, __LINE__, bus_addr); |
| 637 | DBG("%s:%d: not found: len %lxh\n", | 912 | DBG("%s:%d: not found: len %lxh\n", |
| @@ -647,94 +922,166 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | |||
| 647 | 922 | ||
| 648 | if (!c->usage_count) { | 923 | if (!c->usage_count) { |
| 649 | list_del(&c->link); | 924 | list_del(&c->link); |
| 650 | dma_free_chunk(c); | 925 | dma_sb_free_chunk(c); |
| 651 | } | 926 | } |
| 652 | 927 | ||
| 653 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 928 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
| 654 | return 0; | 929 | return 0; |
| 655 | } | 930 | } |
| 656 | 931 | ||
| 932 | static int dma_ioc0_unmap_area(struct ps3_dma_region *r, | ||
| 933 | unsigned long bus_addr, unsigned long len) | ||
| 934 | { | ||
| 935 | unsigned long flags; | ||
| 936 | struct dma_chunk *c; | ||
| 937 | |||
| 938 | DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len); | ||
| 939 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
| 940 | c = dma_find_chunk(r, bus_addr, len); | ||
| 941 | |||
| 942 | if (!c) { | ||
| 943 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, | ||
| 944 | 1 << r->page_size); | ||
| 945 | unsigned long aligned_len = _ALIGN_UP(len + bus_addr | ||
| 946 | - aligned_bus, | ||
| 947 | 1 << r->page_size); | ||
| 948 | DBG("%s:%d: not found: bus_addr %lxh\n", | ||
| 949 | __func__, __LINE__, bus_addr); | ||
| 950 | DBG("%s:%d: not found: len %lxh\n", | ||
| 951 | __func__, __LINE__, len); | ||
| 952 | DBG("%s:%d: not found: aligned_bus %lxh\n", | ||
| 953 | __func__, __LINE__, aligned_bus); | ||
| 954 | DBG("%s:%d: not found: aligned_len %lxh\n", | ||
| 955 | __func__, __LINE__, aligned_len); | ||
| 956 | BUG(); | ||
| 957 | } | ||
| 958 | |||
| 959 | c->usage_count--; | ||
| 960 | |||
| 961 | if (!c->usage_count) { | ||
| 962 | list_del(&c->link); | ||
| 963 | dma_ioc0_free_chunk(c); | ||
| 964 | } | ||
| 965 | |||
| 966 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
| 967 | DBG("%s: end\n", __func__); | ||
| 968 | return 0; | ||
| 969 | } | ||
| 970 | |||
| 657 | /** | 971 | /** |
| 658 | * dma_region_create_linear - Setup a linear dma maping for a device. | 972 | * dma_sb_region_create_linear - Setup a linear dma mapping for a device. |
| 659 | * @r: Pointer to a struct ps3_dma_region. | 973 | * @r: Pointer to a struct ps3_dma_region. |
| 660 | * | 974 | * |
| 661 | * This routine creates an HV dma region for the device and maps all available | 975 | * This routine creates an HV dma region for the device and maps all available |
| 662 | * ram into the io controller bus address space. | 976 | * ram into the io controller bus address space. |
| 663 | */ | 977 | */ |
| 664 | 978 | ||
| 665 | static int dma_region_create_linear(struct ps3_dma_region *r) | 979 | static int dma_sb_region_create_linear(struct ps3_dma_region *r) |
| 666 | { | 980 | { |
| 667 | int result; | 981 | int result; |
| 668 | unsigned long tmp; | 982 | unsigned long virt_addr, len, tmp; |
| 669 | 983 | ||
| 670 | /* force 16M dma pages for linear mapping */ | 984 | if (r->len > 16*1024*1024) { /* FIXME: need proper fix */ |
| 671 | 985 | /* force 16M dma pages for linear mapping */ | |
| 672 | if (r->page_size != PS3_DMA_16M) { | 986 | if (r->page_size != PS3_DMA_16M) { |
| 673 | pr_info("%s:%d: forcing 16M pages for linear map\n", | 987 | pr_info("%s:%d: forcing 16M pages for linear map\n", |
| 674 | __func__, __LINE__); | 988 | __func__, __LINE__); |
| 675 | r->page_size = PS3_DMA_16M; | 989 | r->page_size = PS3_DMA_16M; |
| 990 | r->len = _ALIGN_UP(r->len, 1 << r->page_size); | ||
| 991 | } | ||
| 676 | } | 992 | } |
| 677 | 993 | ||
| 678 | result = dma_region_create(r); | 994 | result = dma_sb_region_create(r); |
| 679 | BUG_ON(result); | 995 | BUG_ON(result); |
| 680 | 996 | ||
| 681 | result = dma_map_area(r, map.rm.base, map.rm.size, &tmp); | 997 | if (r->offset < map.rm.size) { |
| 682 | BUG_ON(result); | 998 | /* Map (part of) 1st RAM chunk */ |
| 683 | 999 | virt_addr = map.rm.base + r->offset; | |
| 684 | if (USE_LPAR_ADDR) | 1000 | len = map.rm.size - r->offset; |
| 685 | result = dma_map_area(r, map.r1.base, map.r1.size, | 1001 | if (len > r->len) |
| 686 | &tmp); | 1002 | len = r->len; |
| 687 | else | 1003 | result = dma_sb_map_area(r, virt_addr, len, &tmp, |
| 688 | result = dma_map_area(r, map.rm.size, map.r1.size, | 1004 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); |
| 689 | &tmp); | 1005 | BUG_ON(result); |
| 1006 | } | ||
| 690 | 1007 | ||
| 691 | BUG_ON(result); | 1008 | if (r->offset + r->len > map.rm.size) { |
| 1009 | /* Map (part of) 2nd RAM chunk */ | ||
| 1010 | virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; | ||
| 1011 | len = r->len; | ||
| 1012 | if (r->offset >= map.rm.size) | ||
| 1013 | virt_addr += r->offset - map.rm.size; | ||
| 1014 | else | ||
| 1015 | len -= map.rm.size - r->offset; | ||
| 1016 | result = dma_sb_map_area(r, virt_addr, len, &tmp, | ||
| 1017 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); | ||
| 1018 | BUG_ON(result); | ||
| 1019 | } | ||
| 692 | 1020 | ||
| 693 | return result; | 1021 | return result; |
| 694 | } | 1022 | } |
| 695 | 1023 | ||
| 696 | /** | 1024 | /** |
| 697 | * dma_region_free_linear - Free a linear dma mapping for a device. | 1025 | * dma_sb_region_free_linear - Free a linear dma mapping for a device. |
| 698 | * @r: Pointer to a struct ps3_dma_region. | 1026 | * @r: Pointer to a struct ps3_dma_region. |
| 699 | * | 1027 | * |
| 700 | * This routine will unmap all mapped areas and free the HV dma region. | 1028 | * This routine will unmap all mapped areas and free the HV dma region. |
| 701 | */ | 1029 | */ |
| 702 | 1030 | ||
| 703 | static int dma_region_free_linear(struct ps3_dma_region *r) | 1031 | static int dma_sb_region_free_linear(struct ps3_dma_region *r) |
| 704 | { | 1032 | { |
| 705 | int result; | 1033 | int result; |
| 1034 | unsigned long bus_addr, len, lpar_addr; | ||
| 1035 | |||
| 1036 | if (r->offset < map.rm.size) { | ||
| 1037 | /* Unmap (part of) 1st RAM chunk */ | ||
| 1038 | lpar_addr = map.rm.base + r->offset; | ||
| 1039 | len = map.rm.size - r->offset; | ||
| 1040 | if (len > r->len) | ||
| 1041 | len = r->len; | ||
| 1042 | bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); | ||
| 1043 | result = dma_sb_unmap_area(r, bus_addr, len); | ||
| 1044 | BUG_ON(result); | ||
| 1045 | } | ||
| 706 | 1046 | ||
| 707 | result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size); | 1047 | if (r->offset + r->len > map.rm.size) { |
| 708 | BUG_ON(result); | 1048 | /* Unmap (part of) 2nd RAM chunk */ |
| 709 | 1049 | lpar_addr = map.r1.base; | |
| 710 | result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base), | 1050 | len = r->len; |
| 711 | map.r1.size); | 1051 | if (r->offset >= map.rm.size) |
| 712 | BUG_ON(result); | 1052 | lpar_addr += r->offset - map.rm.size; |
| 1053 | else | ||
| 1054 | len -= map.rm.size - r->offset; | ||
| 1055 | bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); | ||
| 1056 | result = dma_sb_unmap_area(r, bus_addr, len); | ||
| 1057 | BUG_ON(result); | ||
| 1058 | } | ||
| 713 | 1059 | ||
| 714 | result = dma_region_free(r); | 1060 | result = dma_sb_region_free(r); |
| 715 | BUG_ON(result); | 1061 | BUG_ON(result); |
| 716 | 1062 | ||
| 717 | return result; | 1063 | return result; |
| 718 | } | 1064 | } |
| 719 | 1065 | ||
| 720 | /** | 1066 | /** |
| 721 | * dma_map_area_linear - Map an area of memory into a device dma region. | 1067 | * dma_sb_map_area_linear - Map an area of memory into a device dma region. |
| 722 | * @r: Pointer to a struct ps3_dma_region. | 1068 | * @r: Pointer to a struct ps3_dma_region. |
| 723 | * @virt_addr: Starting virtual address of the area to map. | 1069 | * @virt_addr: Starting virtual address of the area to map. |
| 724 | * @len: Length in bytes of the area to map. | 1070 | * @len: Length in bytes of the area to map. |
| 725 | * @bus_addr: A pointer to return the starting ioc bus address of the area to | 1071 | * @bus_addr: A pointer to return the starting ioc bus address of the area to |
| 726 | * map. | 1072 | * map. |
| 727 | * | 1073 | * |
| 728 | * This routine just returns the coresponding bus address. Actual mapping | 1074 | * This routine just returns the corresponding bus address. Actual mapping |
| 729 | * occurs in dma_region_create_linear(). | 1075 | * occurs in dma_region_create_linear(). |
| 730 | */ | 1076 | */ |
| 731 | 1077 | ||
| 732 | static int dma_map_area_linear(struct ps3_dma_region *r, | 1078 | static int dma_sb_map_area_linear(struct ps3_dma_region *r, |
| 733 | unsigned long virt_addr, unsigned long len, unsigned long *bus_addr) | 1079 | unsigned long virt_addr, unsigned long len, unsigned long *bus_addr, |
| 1080 | u64 iopte_flag) | ||
| 734 | { | 1081 | { |
| 735 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | 1082 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) |
| 736 | : virt_addr; | 1083 | : virt_addr; |
| 737 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | 1084 | *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); |
| 738 | return 0; | 1085 | return 0; |
| 739 | } | 1086 | } |
| 740 | 1087 | ||
| @@ -744,42 +1091,98 @@ static int dma_map_area_linear(struct ps3_dma_region *r, | |||
| 744 | * @bus_addr: The starting ioc bus address of the area to unmap. | 1091 | * @bus_addr: The starting ioc bus address of the area to unmap. |
| 745 | * @len: Length in bytes of the area to unmap. | 1092 | * @len: Length in bytes of the area to unmap. |
| 746 | * | 1093 | * |
| 747 | * This routine does nothing. Unmapping occurs in dma_region_free_linear(). | 1094 | * This routine does nothing. Unmapping occurs in dma_sb_region_free_linear(). |
| 748 | */ | 1095 | */ |
| 749 | 1096 | ||
| 750 | static int dma_unmap_area_linear(struct ps3_dma_region *r, | 1097 | static int dma_sb_unmap_area_linear(struct ps3_dma_region *r, |
| 751 | unsigned long bus_addr, unsigned long len) | 1098 | unsigned long bus_addr, unsigned long len) |
| 752 | { | 1099 | { |
| 753 | return 0; | 1100 | return 0; |
| 1101 | }; | ||
| 1102 | |||
| 1103 | static const struct ps3_dma_region_ops ps3_dma_sb_region_ops = { | ||
| 1104 | .create = dma_sb_region_create, | ||
| 1105 | .free = dma_sb_region_free, | ||
| 1106 | .map = dma_sb_map_area, | ||
| 1107 | .unmap = dma_sb_unmap_area | ||
| 1108 | }; | ||
| 1109 | |||
| 1110 | static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = { | ||
| 1111 | .create = dma_sb_region_create_linear, | ||
| 1112 | .free = dma_sb_region_free_linear, | ||
| 1113 | .map = dma_sb_map_area_linear, | ||
| 1114 | .unmap = dma_sb_unmap_area_linear | ||
| 1115 | }; | ||
| 1116 | |||
| 1117 | static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = { | ||
| 1118 | .create = dma_ioc0_region_create, | ||
| 1119 | .free = dma_ioc0_region_free, | ||
| 1120 | .map = dma_ioc0_map_area, | ||
| 1121 | .unmap = dma_ioc0_unmap_area | ||
| 1122 | }; | ||
| 1123 | |||
| 1124 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, | ||
| 1125 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, | ||
| 1126 | enum ps3_dma_region_type region_type, void *addr, unsigned long len) | ||
| 1127 | { | ||
| 1128 | unsigned long lpar_addr; | ||
| 1129 | |||
| 1130 | lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0; | ||
| 1131 | |||
| 1132 | r->dev = dev; | ||
| 1133 | r->page_size = page_size; | ||
| 1134 | r->region_type = region_type; | ||
| 1135 | r->offset = lpar_addr; | ||
| 1136 | if (r->offset >= map.rm.size) | ||
| 1137 | r->offset -= map.r1.offset; | ||
| 1138 | r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size); | ||
| 1139 | |||
| 1140 | switch (dev->dev_type) { | ||
| 1141 | case PS3_DEVICE_TYPE_SB: | ||
| 1142 | r->region_ops = (USE_DYNAMIC_DMA) | ||
| 1143 | ? &ps3_dma_sb_region_ops | ||
| 1144 | : &ps3_dma_sb_region_linear_ops; | ||
| 1145 | break; | ||
| 1146 | case PS3_DEVICE_TYPE_IOC0: | ||
| 1147 | r->region_ops = &ps3_dma_ioc0_region_ops; | ||
| 1148 | break; | ||
| 1149 | default: | ||
| 1150 | BUG(); | ||
| 1151 | return -EINVAL; | ||
| 1152 | } | ||
| 1153 | return 0; | ||
| 754 | } | 1154 | } |
| 1155 | EXPORT_SYMBOL(ps3_dma_region_init); | ||
| 755 | 1156 | ||
| 756 | int ps3_dma_region_create(struct ps3_dma_region *r) | 1157 | int ps3_dma_region_create(struct ps3_dma_region *r) |
| 757 | { | 1158 | { |
| 758 | return (USE_DYNAMIC_DMA) | 1159 | BUG_ON(!r); |
| 759 | ? dma_region_create(r) | 1160 | BUG_ON(!r->region_ops); |
| 760 | : dma_region_create_linear(r); | 1161 | BUG_ON(!r->region_ops->create); |
| 1162 | return r->region_ops->create(r); | ||
| 761 | } | 1163 | } |
| 1164 | EXPORT_SYMBOL(ps3_dma_region_create); | ||
| 762 | 1165 | ||
| 763 | int ps3_dma_region_free(struct ps3_dma_region *r) | 1166 | int ps3_dma_region_free(struct ps3_dma_region *r) |
| 764 | { | 1167 | { |
| 765 | return (USE_DYNAMIC_DMA) | 1168 | BUG_ON(!r); |
| 766 | ? dma_region_free(r) | 1169 | BUG_ON(!r->region_ops); |
| 767 | : dma_region_free_linear(r); | 1170 | BUG_ON(!r->region_ops->free); |
| 1171 | return r->region_ops->free(r); | ||
| 768 | } | 1172 | } |
| 1173 | EXPORT_SYMBOL(ps3_dma_region_free); | ||
| 769 | 1174 | ||
| 770 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | 1175 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, |
| 771 | unsigned long len, unsigned long *bus_addr) | 1176 | unsigned long len, unsigned long *bus_addr, |
| 1177 | u64 iopte_flag) | ||
| 772 | { | 1178 | { |
| 773 | return (USE_DYNAMIC_DMA) | 1179 | return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag); |
| 774 | ? dma_map_area(r, virt_addr, len, bus_addr) | ||
| 775 | : dma_map_area_linear(r, virt_addr, len, bus_addr); | ||
| 776 | } | 1180 | } |
| 777 | 1181 | ||
| 778 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | 1182 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, |
| 779 | unsigned long len) | 1183 | unsigned long len) |
| 780 | { | 1184 | { |
| 781 | return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len) | 1185 | return r->region_ops->unmap(r, bus_addr, len); |
| 782 | : dma_unmap_area_linear(r, bus_addr, len); | ||
| 783 | } | 1186 | } |
| 784 | 1187 | ||
| 785 | /*============================================================================*/ | 1188 | /*============================================================================*/ |
| @@ -810,12 +1213,13 @@ void __init ps3_mm_init(void) | |||
| 810 | BUG_ON(map.rm.base); | 1213 | BUG_ON(map.rm.base); |
| 811 | BUG_ON(!map.rm.size); | 1214 | BUG_ON(!map.rm.size); |
| 812 | 1215 | ||
| 813 | lmb_add(map.rm.base, map.rm.size); | ||
| 814 | lmb_analyze(); | ||
| 815 | 1216 | ||
| 816 | /* arrange to do this in ps3_mm_add_memory */ | 1217 | /* arrange to do this in ps3_mm_add_memory */ |
| 817 | ps3_mm_region_create(&map.r1, map.total - map.rm.size); | 1218 | ps3_mm_region_create(&map.r1, map.total - map.rm.size); |
| 818 | 1219 | ||
| 1220 | /* correct map.total for the real total amount of memory we use */ | ||
| 1221 | map.total = map.rm.size + map.r1.size; | ||
| 1222 | |||
| 819 | DBG(" <- %s:%d\n", __func__, __LINE__); | 1223 | DBG(" <- %s:%d\n", __func__, __LINE__); |
| 820 | } | 1224 | } |
| 821 | 1225 | ||
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index 5c3da08bc0c4..b70e474014f0 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
| @@ -133,7 +133,7 @@ struct saved_params { | |||
| 133 | } static saved_params; | 133 | } static saved_params; |
| 134 | 134 | ||
| 135 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) | 135 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) |
| 136 | static void _dump_header(const struct os_area_header __iomem *h, const char* func, | 136 | static void _dump_header(const struct os_area_header *h, const char *func, |
| 137 | int line) | 137 | int line) |
| 138 | { | 138 | { |
| 139 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, | 139 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, |
| @@ -151,7 +151,7 @@ static void _dump_header(const struct os_area_header __iomem *h, const char* fun | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | #define dump_params(_a) _dump_params(_a, __func__, __LINE__) | 153 | #define dump_params(_a) _dump_params(_a, __func__, __LINE__) |
| 154 | static void _dump_params(const struct os_area_params __iomem *p, const char* func, | 154 | static void _dump_params(const struct os_area_params *p, const char *func, |
| 155 | int line) | 155 | int line) |
| 156 | { | 156 | { |
| 157 | pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); | 157 | pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); |
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index ca04f03305c7..87d52060fec0 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
| @@ -41,6 +41,7 @@ void ps3_mm_shutdown(void); | |||
| 41 | /* irq */ | 41 | /* irq */ |
| 42 | 42 | ||
| 43 | void ps3_init_IRQ(void); | 43 | void ps3_init_IRQ(void); |
| 44 | void ps3_shutdown_IRQ(int cpu); | ||
| 44 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); | 45 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); |
| 45 | 46 | ||
| 46 | /* smp */ | 47 | /* smp */ |
| @@ -82,6 +83,7 @@ enum ps3_dev_type { | |||
| 82 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ | 83 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ |
| 83 | PS3_DEV_TYPE_SB_GPIO = 6, | 84 | PS3_DEV_TYPE_SB_GPIO = 6, |
| 84 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ | 85 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ |
| 86 | PS3_DEV_TYPE_NOACCESS = 255, | ||
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 89 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
| @@ -129,24 +131,28 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, | |||
| 129 | /* repository bus enumerators */ | 131 | /* repository bus enumerators */ |
| 130 | 132 | ||
| 131 | struct ps3_repository_device { | 133 | struct ps3_repository_device { |
| 134 | enum ps3_bus_type bus_type; | ||
| 132 | unsigned int bus_index; | 135 | unsigned int bus_index; |
| 136 | unsigned int bus_id; | ||
| 137 | enum ps3_dev_type dev_type; | ||
| 133 | unsigned int dev_index; | 138 | unsigned int dev_index; |
| 134 | struct ps3_device_id did; | 139 | unsigned int dev_id; |
| 135 | }; | 140 | }; |
| 136 | 141 | ||
| 137 | int ps3_repository_find_device(enum ps3_bus_type bus_type, | 142 | static inline struct ps3_repository_device *ps3_repository_bump_device( |
| 138 | enum ps3_dev_type dev_type, | 143 | struct ps3_repository_device *repo) |
| 139 | const struct ps3_repository_device *start_dev, | ||
| 140 | struct ps3_repository_device *dev); | ||
| 141 | static inline int ps3_repository_find_first_device( | ||
| 142 | enum ps3_bus_type bus_type, enum ps3_dev_type dev_type, | ||
| 143 | struct ps3_repository_device *dev) | ||
| 144 | { | 144 | { |
| 145 | return ps3_repository_find_device(bus_type, dev_type, NULL, dev); | 145 | repo->dev_index++; |
| 146 | return repo; | ||
| 146 | } | 147 | } |
| 147 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | 148 | int ps3_repository_find_device(struct ps3_repository_device *repo); |
| 149 | int ps3_repository_find_devices(enum ps3_bus_type bus_type, | ||
| 150 | int (*callback)(const struct ps3_repository_device *repo)); | ||
| 151 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, | ||
| 152 | unsigned int *bus_index); | ||
| 153 | int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, | ||
| 148 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); | 154 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); |
| 149 | int ps3_repository_find_reg(const struct ps3_repository_device *dev, | 155 | int ps3_repository_find_reg(const struct ps3_repository_device *repo, |
| 150 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len); | 156 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len); |
| 151 | 157 | ||
| 152 | /* repository block device info */ | 158 | /* repository block device info */ |
| @@ -216,4 +222,19 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); | |||
| 216 | int ps3_repository_read_spu_resource_id(unsigned int res_index, | 222 | int ps3_repository_read_spu_resource_id(unsigned int res_index, |
| 217 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); | 223 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); |
| 218 | 224 | ||
| 225 | /* repository vuart info */ | ||
| 226 | |||
| 227 | int ps3_repository_read_vuart_av_port(unsigned int *port); | ||
| 228 | int ps3_repository_read_vuart_sysmgr_port(unsigned int *port); | ||
| 229 | |||
| 230 | /* Page table entries */ | ||
| 231 | #define IOPTE_PP_W 0x8000000000000000ul /* protection: write */ | ||
| 232 | #define IOPTE_PP_R 0x4000000000000000ul /* protection: read */ | ||
| 233 | #define IOPTE_M 0x2000000000000000ul /* coherency required */ | ||
| 234 | #define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ | ||
| 235 | #define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ | ||
| 236 | #define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ | ||
| 237 | #define IOPTE_H 0x0000000000000800ul /* cache hint */ | ||
| 238 | #define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ | ||
| 239 | |||
| 219 | #endif | 240 | #endif |
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index ae586a0e5d3f..8cc37cfea0f2 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c | |||
| @@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | |||
| 138 | pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", | 138 | pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", |
| 139 | __func__, __LINE__, ps3_result(result)); | 139 | __func__, __LINE__, ps3_result(result)); |
| 140 | dump_node_name(lpar_id, n1, n2, n3, n4); | 140 | dump_node_name(lpar_id, n1, n2, n3, n4); |
| 141 | return result; | 141 | return -ENOENT; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | dump_node(lpar_id, n1, n2, n3, n4, v1, v2); | 144 | dump_node(lpar_id, n1, n2, n3, n4, v1, v2); |
| @@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | |||
| 155 | pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", | 155 | pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", |
| 156 | __func__, __LINE__, v2); | 156 | __func__, __LINE__, v2); |
| 157 | 157 | ||
| 158 | return result; | 158 | return 0; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 161 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
| @@ -314,324 +314,140 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, | |||
| 314 | reg_index, bus_addr, len); | 314 | reg_index, bus_addr, len); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | #if defined(DEBUG) | ||
| 318 | int ps3_repository_dump_resource_info(unsigned int bus_index, | ||
| 319 | unsigned int dev_index) | ||
| 320 | { | ||
| 321 | int result = 0; | ||
| 322 | unsigned int res_index; | ||
| 323 | 317 | ||
| 324 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
| 325 | bus_index, dev_index); | ||
| 326 | 318 | ||
| 327 | for (res_index = 0; res_index < 10; res_index++) { | 319 | int ps3_repository_find_device(struct ps3_repository_device *repo) |
| 328 | enum ps3_interrupt_type intr_type; | 320 | { |
| 329 | unsigned int interrupt_id; | 321 | int result; |
| 322 | struct ps3_repository_device tmp = *repo; | ||
| 323 | unsigned int num_dev; | ||
| 330 | 324 | ||
| 331 | result = ps3_repository_read_dev_intr(bus_index, dev_index, | 325 | BUG_ON(repo->bus_index > 10); |
| 332 | res_index, &intr_type, &interrupt_id); | 326 | BUG_ON(repo->dev_index > 10); |
| 333 | 327 | ||
| 334 | if (result) { | 328 | result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); |
| 335 | if (result != LV1_NO_ENTRY) | ||
| 336 | pr_debug("%s:%d ps3_repository_read_dev_intr" | ||
| 337 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 338 | bus_index, dev_index); | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | 329 | ||
| 342 | pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", | 330 | if (result) { |
| 343 | __func__, __LINE__, bus_index, dev_index, intr_type, | 331 | pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); |
| 344 | interrupt_id); | 332 | return result; |
| 345 | } | 333 | } |
| 346 | 334 | ||
| 347 | for (res_index = 0; res_index < 10; res_index++) { | 335 | pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", |
| 348 | enum ps3_reg_type reg_type; | 336 | __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, |
| 349 | u64 bus_addr; | 337 | num_dev); |
| 350 | u64 len; | ||
| 351 | |||
| 352 | result = ps3_repository_read_dev_reg(bus_index, dev_index, | ||
| 353 | res_index, ®_type, &bus_addr, &len); | ||
| 354 | 338 | ||
| 355 | if (result) { | 339 | if (tmp.dev_index >= num_dev) { |
| 356 | if (result != LV1_NO_ENTRY) | 340 | pr_debug("%s:%d: no device found\n", __func__, __LINE__); |
| 357 | pr_debug("%s:%d ps3_repository_read_dev_reg" | 341 | return -ENODEV; |
| 358 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 359 | bus_index, dev_index); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | |||
| 363 | pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", | ||
| 364 | __func__, __LINE__, bus_index, dev_index, reg_type, | ||
| 365 | bus_addr, len); | ||
| 366 | } | 342 | } |
| 367 | 343 | ||
| 368 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 344 | result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, |
| 369 | return result; | 345 | &tmp.dev_type); |
| 370 | } | ||
| 371 | |||
| 372 | static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index) | ||
| 373 | { | ||
| 374 | int result = 0; | ||
| 375 | unsigned int num_regions, region_index; | ||
| 376 | u64 port, blk_size, num_blocks; | ||
| 377 | |||
| 378 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
| 379 | bus_index, dev_index); | ||
| 380 | 346 | ||
| 381 | result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port, | ||
| 382 | &blk_size, &num_blocks, &num_regions); | ||
| 383 | if (result) { | 347 | if (result) { |
| 384 | pr_debug("%s:%d ps3_repository_read_stor_dev_info" | 348 | pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); |
| 385 | " (%u:%u) failed\n", __func__, __LINE__, | 349 | return result; |
| 386 | bus_index, dev_index); | ||
| 387 | goto out; | ||
| 388 | } | 350 | } |
| 389 | 351 | ||
| 390 | pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " | 352 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, |
| 391 | "%lu, num_regions %u\n", | 353 | &tmp.dev_id); |
| 392 | __func__, __LINE__, bus_index, dev_index, port, | ||
| 393 | blk_size, num_blocks, num_regions); | ||
| 394 | |||
| 395 | for (region_index = 0; region_index < num_regions; region_index++) { | ||
| 396 | unsigned int region_id; | ||
| 397 | u64 region_start, region_size; | ||
| 398 | |||
| 399 | result = ps3_repository_read_stor_dev_region(bus_index, | ||
| 400 | dev_index, region_index, ®ion_id, ®ion_start, | ||
| 401 | ®ion_size); | ||
| 402 | if (result) { | ||
| 403 | pr_debug("%s:%d ps3_repository_read_stor_dev_region" | ||
| 404 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 405 | bus_index, dev_index); | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | 354 | ||
| 409 | pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", | 355 | if (result) { |
| 410 | __func__, __LINE__, bus_index, dev_index, region_id, | 356 | pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, |
| 411 | region_start, region_size); | 357 | __LINE__); |
| 358 | return result; | ||
| 412 | } | 359 | } |
| 413 | 360 | ||
| 414 | out: | 361 | pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", |
| 415 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 362 | __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); |
| 416 | return result; | ||
| 417 | } | ||
| 418 | |||
| 419 | static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type, | ||
| 420 | unsigned int num_dev) | ||
| 421 | { | ||
| 422 | int result = 0; | ||
| 423 | unsigned int dev_index; | ||
| 424 | |||
| 425 | pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index); | ||
| 426 | |||
| 427 | for (dev_index = 0; dev_index < num_dev; dev_index++) { | ||
| 428 | enum ps3_dev_type dev_type; | ||
| 429 | unsigned int dev_id; | ||
| 430 | |||
| 431 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
| 432 | &dev_type); | ||
| 433 | |||
| 434 | if (result) { | ||
| 435 | pr_debug("%s:%d ps3_repository_read_dev_type" | ||
| 436 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 437 | bus_index, dev_index); | ||
| 438 | break; | ||
| 439 | } | ||
| 440 | |||
| 441 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
| 442 | &dev_id); | ||
| 443 | |||
| 444 | if (result) { | ||
| 445 | pr_debug("%s:%d ps3_repository_read_dev_id" | ||
| 446 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 447 | bus_index, dev_index); | ||
| 448 | continue; | ||
| 449 | } | ||
| 450 | 363 | ||
| 451 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | 364 | *repo = tmp; |
| 452 | __LINE__, bus_index, dev_index, dev_type, dev_id); | 365 | return 0; |
| 453 | |||
| 454 | ps3_repository_dump_resource_info(bus_index, dev_index); | ||
| 455 | |||
| 456 | if (bus_type == PS3_BUS_TYPE_STORAGE) | ||
| 457 | dump_stor_dev_info(bus_index, dev_index); | ||
| 458 | } | ||
| 459 | |||
| 460 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 461 | return result; | ||
| 462 | } | 366 | } |
| 463 | 367 | ||
| 464 | int ps3_repository_dump_bus_info(void) | 368 | int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, |
| 369 | int (*callback)(const struct ps3_repository_device *repo)) | ||
| 465 | { | 370 | { |
| 466 | int result = 0; | 371 | int result = 0; |
| 467 | unsigned int bus_index; | 372 | struct ps3_repository_device repo; |
| 468 | 373 | ||
| 469 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 374 | pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); |
| 470 | 375 | ||
| 471 | for (bus_index = 0; bus_index < 10; bus_index++) { | 376 | for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { |
| 472 | enum ps3_bus_type bus_type; | ||
| 473 | unsigned int bus_id; | ||
| 474 | unsigned int num_dev; | ||
| 475 | 377 | ||
| 476 | result = ps3_repository_read_bus_type(bus_index, &bus_type); | 378 | result = ps3_repository_read_bus_type(repo.bus_index, |
| 379 | &repo.bus_type); | ||
| 477 | 380 | ||
| 478 | if (result) { | 381 | if (result) { |
| 479 | pr_debug("%s:%d read_bus_type(%u) failed\n", | 382 | pr_debug("%s:%d read_bus_type(%u) failed\n", |
| 480 | __func__, __LINE__, bus_index); | 383 | __func__, __LINE__, repo.bus_index); |
| 481 | break; | 384 | break; |
| 482 | } | 385 | } |
| 483 | 386 | ||
| 484 | result = ps3_repository_read_bus_id(bus_index, &bus_id); | 387 | if (repo.bus_type != bus_type) { |
| 485 | 388 | pr_debug("%s:%d: skip, bus_type %u\n", __func__, | |
| 486 | if (result) { | 389 | __LINE__, repo.bus_type); |
| 487 | pr_debug("%s:%d read_bus_id(%u) failed\n", | ||
| 488 | __func__, __LINE__, bus_index); | ||
| 489 | continue; | 390 | continue; |
| 490 | } | 391 | } |
| 491 | 392 | ||
| 492 | if (bus_index != bus_id) | 393 | result = ps3_repository_read_bus_id(repo.bus_index, |
| 493 | pr_debug("%s:%d bus_index != bus_id\n", | 394 | &repo.bus_id); |
| 494 | __func__, __LINE__); | ||
| 495 | |||
| 496 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
| 497 | 395 | ||
| 498 | if (result) { | 396 | if (result) { |
| 499 | pr_debug("%s:%d read_bus_num_dev(%u) failed\n", | 397 | pr_debug("%s:%d read_bus_id(%u) failed\n", |
| 500 | __func__, __LINE__, bus_index); | 398 | __func__, __LINE__, repo.bus_index); |
| 501 | continue; | 399 | continue; |
| 502 | } | 400 | } |
| 503 | 401 | ||
| 504 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | 402 | for (repo.dev_index = 0; ; repo.dev_index++) { |
| 505 | __func__, __LINE__, bus_index, bus_type, bus_id, | 403 | result = ps3_repository_find_device(&repo); |
| 506 | num_dev); | ||
| 507 | 404 | ||
| 508 | dump_device_info(bus_index, bus_type, num_dev); | 405 | if (result == -ENODEV) { |
| 509 | } | 406 | result = 0; |
| 407 | break; | ||
| 408 | } else if (result) | ||
| 409 | break; | ||
| 510 | 410 | ||
| 511 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 411 | result = callback(&repo); |
| 512 | return result; | ||
| 513 | } | ||
| 514 | #endif /* defined(DEBUG) */ | ||
| 515 | |||
| 516 | static int find_device(unsigned int bus_index, unsigned int num_dev, | ||
| 517 | unsigned int start_dev_index, enum ps3_dev_type dev_type, | ||
| 518 | struct ps3_repository_device *dev) | ||
| 519 | { | ||
| 520 | int result = 0; | ||
| 521 | unsigned int dev_index; | ||
| 522 | 412 | ||
| 523 | pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type); | 413 | if (result) { |
| 524 | 414 | pr_debug("%s:%d: abort at callback\n", __func__, | |
| 525 | dev->dev_index = UINT_MAX; | 415 | __LINE__); |
| 526 | 416 | break; | |
| 527 | for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) { | 417 | } |
| 528 | enum ps3_dev_type x; | ||
| 529 | |||
| 530 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
| 531 | &x); | ||
| 532 | |||
| 533 | if (result) { | ||
| 534 | pr_debug("%s:%d read_dev_type failed\n", | ||
| 535 | __func__, __LINE__); | ||
| 536 | return result; | ||
| 537 | } | 418 | } |
| 538 | 419 | break; | |
| 539 | if (x == dev_type) | ||
| 540 | break; | ||
| 541 | } | ||
| 542 | |||
| 543 | if (dev_index == num_dev) | ||
| 544 | return -1; | ||
| 545 | |||
| 546 | pr_debug("%s:%d: found dev_type %u at dev_index %u\n", | ||
| 547 | __func__, __LINE__, dev_type, dev_index); | ||
| 548 | |||
| 549 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
| 550 | &dev->did.dev_id); | ||
| 551 | |||
| 552 | if (result) { | ||
| 553 | pr_debug("%s:%d read_dev_id failed\n", | ||
| 554 | __func__, __LINE__); | ||
| 555 | return result; | ||
| 556 | } | 420 | } |
| 557 | 421 | ||
| 558 | dev->dev_index = dev_index; | 422 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
| 559 | |||
| 560 | pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__, | ||
| 561 | dev->did.dev_id); | ||
| 562 | |||
| 563 | return result; | 423 | return result; |
| 564 | } | 424 | } |
| 565 | 425 | ||
| 566 | int ps3_repository_find_device (enum ps3_bus_type bus_type, | 426 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, |
| 567 | enum ps3_dev_type dev_type, | 427 | unsigned int *bus_index) |
| 568 | const struct ps3_repository_device *start_dev, | ||
| 569 | struct ps3_repository_device *dev) | ||
| 570 | { | 428 | { |
| 571 | int result = 0; | 429 | unsigned int i; |
| 572 | unsigned int bus_index; | 430 | enum ps3_bus_type type; |
| 573 | unsigned int num_dev; | 431 | int error; |
| 574 | |||
| 575 | pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__, | ||
| 576 | bus_type, dev_type); | ||
| 577 | |||
| 578 | BUG_ON(start_dev && start_dev->bus_index > 10); | ||
| 579 | |||
| 580 | for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10; | ||
| 581 | bus_index++) { | ||
| 582 | enum ps3_bus_type x; | ||
| 583 | |||
| 584 | result = ps3_repository_read_bus_type(bus_index, &x); | ||
| 585 | 432 | ||
| 586 | if (result) { | 433 | for (i = from; i < 10; i++) { |
| 434 | error = ps3_repository_read_bus_type(i, &type); | ||
| 435 | if (error) { | ||
| 587 | pr_debug("%s:%d read_bus_type failed\n", | 436 | pr_debug("%s:%d read_bus_type failed\n", |
| 588 | __func__, __LINE__); | 437 | __func__, __LINE__); |
| 589 | dev->bus_index = UINT_MAX; | 438 | *bus_index = UINT_MAX; |
| 590 | return result; | 439 | return error; |
| 440 | } | ||
| 441 | if (type == bus_type) { | ||
| 442 | *bus_index = i; | ||
| 443 | return 0; | ||
| 591 | } | 444 | } |
| 592 | if (x == bus_type) | ||
| 593 | break; | ||
| 594 | } | ||
| 595 | |||
| 596 | if (bus_index >= 10) | ||
| 597 | return -ENODEV; | ||
| 598 | |||
| 599 | pr_debug("%s:%d: found bus_type %u at bus_index %u\n", | ||
| 600 | __func__, __LINE__, bus_type, bus_index); | ||
| 601 | |||
| 602 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
| 603 | |||
| 604 | if (result) { | ||
| 605 | pr_debug("%s:%d read_bus_num_dev failed\n", | ||
| 606 | __func__, __LINE__); | ||
| 607 | return result; | ||
| 608 | } | ||
| 609 | |||
| 610 | result = find_device(bus_index, num_dev, start_dev | ||
| 611 | ? start_dev->dev_index + 1 : 0, dev_type, dev); | ||
| 612 | |||
| 613 | if (result) { | ||
| 614 | pr_debug("%s:%d get_did failed\n", __func__, __LINE__); | ||
| 615 | return result; | ||
| 616 | } | ||
| 617 | |||
| 618 | result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id); | ||
| 619 | |||
| 620 | if (result) { | ||
| 621 | pr_debug("%s:%d read_bus_id failed\n", | ||
| 622 | __func__, __LINE__); | ||
| 623 | return result; | ||
| 624 | } | 445 | } |
| 625 | 446 | *bus_index = UINT_MAX; | |
| 626 | dev->bus_index = bus_index; | 447 | return -ENODEV; |
| 627 | |||
| 628 | pr_debug("%s:%d found: bus_id %u, dev_id %u\n", | ||
| 629 | __func__, __LINE__, dev->did.bus_id, dev->did.dev_id); | ||
| 630 | |||
| 631 | return result; | ||
| 632 | } | 448 | } |
| 633 | 449 | ||
| 634 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | 450 | int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, |
| 635 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) | 451 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) |
| 636 | { | 452 | { |
| 637 | int result = 0; | 453 | int result = 0; |
| @@ -645,8 +461,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | |||
| 645 | enum ps3_interrupt_type t; | 461 | enum ps3_interrupt_type t; |
| 646 | unsigned int id; | 462 | unsigned int id; |
| 647 | 463 | ||
| 648 | result = ps3_repository_read_dev_intr(dev->bus_index, | 464 | result = ps3_repository_read_dev_intr(repo->bus_index, |
| 649 | dev->dev_index, res_index, &t, &id); | 465 | repo->dev_index, res_index, &t, &id); |
| 650 | 466 | ||
| 651 | if (result) { | 467 | if (result) { |
| 652 | pr_debug("%s:%d read_dev_intr failed\n", | 468 | pr_debug("%s:%d read_dev_intr failed\n", |
| @@ -669,7 +485,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | |||
| 669 | return result; | 485 | return result; |
| 670 | } | 486 | } |
| 671 | 487 | ||
| 672 | int ps3_repository_find_reg(const struct ps3_repository_device *dev, | 488 | int ps3_repository_find_reg(const struct ps3_repository_device *repo, |
| 673 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) | 489 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) |
| 674 | { | 490 | { |
| 675 | int result = 0; | 491 | int result = 0; |
| @@ -684,8 +500,8 @@ int ps3_repository_find_reg(const struct ps3_repository_device *dev, | |||
| 684 | u64 a; | 500 | u64 a; |
| 685 | u64 l; | 501 | u64 l; |
| 686 | 502 | ||
| 687 | result = ps3_repository_read_dev_reg(dev->bus_index, | 503 | result = ps3_repository_read_dev_reg(repo->bus_index, |
| 688 | dev->dev_index, res_index, &t, &a, &l); | 504 | repo->dev_index, res_index, &t, &a, &l); |
| 689 | 505 | ||
| 690 | if (result) { | 506 | if (result) { |
| 691 | pr_debug("%s:%d read_dev_reg failed\n", | 507 | pr_debug("%s:%d read_dev_reg failed\n", |
| @@ -965,6 +781,36 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) | |||
| 965 | return result; | 781 | return result; |
| 966 | } | 782 | } |
| 967 | 783 | ||
| 784 | int ps3_repository_read_vuart_av_port(unsigned int *port) | ||
| 785 | { | ||
| 786 | int result; | ||
| 787 | u64 v1; | ||
| 788 | |||
| 789 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
| 790 | make_first_field("bi", 0), | ||
| 791 | make_field("vir_uart", 0), | ||
| 792 | make_field("port", 0), | ||
| 793 | make_field("avset", 0), | ||
| 794 | &v1, 0); | ||
| 795 | *port = v1; | ||
| 796 | return result; | ||
| 797 | } | ||
| 798 | |||
| 799 | int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) | ||
| 800 | { | ||
| 801 | int result; | ||
| 802 | u64 v1; | ||
| 803 | |||
| 804 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
| 805 | make_first_field("bi", 0), | ||
| 806 | make_field("vir_uart", 0), | ||
| 807 | make_field("port", 0), | ||
| 808 | make_field("sysmgr", 0), | ||
| 809 | &v1, 0); | ||
| 810 | *port = v1; | ||
| 811 | return result; | ||
| 812 | } | ||
| 813 | |||
| 968 | /** | 814 | /** |
| 969 | * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. | 815 | * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. |
| 970 | * address: lpar address of cell_ext_os_area | 816 | * address: lpar address of cell_ext_os_area |
| @@ -1026,3 +872,205 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) | |||
| 1026 | return result ? result | 872 | return result ? result |
| 1027 | : ps3_repository_read_tb_freq(node_id, tb_freq); | 873 | : ps3_repository_read_tb_freq(node_id, tb_freq); |
| 1028 | } | 874 | } |
| 875 | |||
| 876 | #if defined(DEBUG) | ||
| 877 | |||
| 878 | int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) | ||
| 879 | { | ||
| 880 | int result = 0; | ||
| 881 | unsigned int res_index; | ||
| 882 | |||
| 883 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
| 884 | repo->bus_index, repo->dev_index); | ||
| 885 | |||
| 886 | for (res_index = 0; res_index < 10; res_index++) { | ||
| 887 | enum ps3_interrupt_type intr_type; | ||
| 888 | unsigned int interrupt_id; | ||
| 889 | |||
| 890 | result = ps3_repository_read_dev_intr(repo->bus_index, | ||
| 891 | repo->dev_index, res_index, &intr_type, &interrupt_id); | ||
| 892 | |||
| 893 | if (result) { | ||
| 894 | if (result != LV1_NO_ENTRY) | ||
| 895 | pr_debug("%s:%d ps3_repository_read_dev_intr" | ||
| 896 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 897 | repo->bus_index, repo->dev_index); | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | |||
| 901 | pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", | ||
| 902 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
| 903 | intr_type, interrupt_id); | ||
| 904 | } | ||
| 905 | |||
| 906 | for (res_index = 0; res_index < 10; res_index++) { | ||
| 907 | enum ps3_reg_type reg_type; | ||
| 908 | u64 bus_addr; | ||
| 909 | u64 len; | ||
| 910 | |||
| 911 | result = ps3_repository_read_dev_reg(repo->bus_index, | ||
| 912 | repo->dev_index, res_index, ®_type, &bus_addr, &len); | ||
| 913 | |||
| 914 | if (result) { | ||
| 915 | if (result != LV1_NO_ENTRY) | ||
| 916 | pr_debug("%s:%d ps3_repository_read_dev_reg" | ||
| 917 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 918 | repo->bus_index, repo->dev_index); | ||
| 919 | break; | ||
| 920 | } | ||
| 921 | |||
| 922 | pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", | ||
| 923 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
| 924 | reg_type, bus_addr, len); | ||
| 925 | } | ||
| 926 | |||
| 927 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 928 | return result; | ||
| 929 | } | ||
| 930 | |||
| 931 | static int dump_stor_dev_info(struct ps3_repository_device *repo) | ||
| 932 | { | ||
| 933 | int result = 0; | ||
| 934 | unsigned int num_regions, region_index; | ||
| 935 | u64 port, blk_size, num_blocks; | ||
| 936 | |||
| 937 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
| 938 | repo->bus_index, repo->dev_index); | ||
| 939 | |||
| 940 | result = ps3_repository_read_stor_dev_info(repo->bus_index, | ||
| 941 | repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); | ||
| 942 | if (result) { | ||
| 943 | pr_debug("%s:%d ps3_repository_read_stor_dev_info" | ||
| 944 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 945 | repo->bus_index, repo->dev_index); | ||
| 946 | goto out; | ||
| 947 | } | ||
| 948 | |||
| 949 | pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " | ||
| 950 | "%lu, num_regions %u\n", | ||
| 951 | __func__, __LINE__, repo->bus_index, repo->dev_index, port, | ||
| 952 | blk_size, num_blocks, num_regions); | ||
| 953 | |||
| 954 | for (region_index = 0; region_index < num_regions; region_index++) { | ||
| 955 | unsigned int region_id; | ||
| 956 | u64 region_start, region_size; | ||
| 957 | |||
| 958 | result = ps3_repository_read_stor_dev_region(repo->bus_index, | ||
| 959 | repo->dev_index, region_index, ®ion_id, | ||
| 960 | ®ion_start, ®ion_size); | ||
| 961 | if (result) { | ||
| 962 | pr_debug("%s:%d ps3_repository_read_stor_dev_region" | ||
| 963 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 964 | repo->bus_index, repo->dev_index); | ||
| 965 | break; | ||
| 966 | } | ||
| 967 | |||
| 968 | pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", | ||
| 969 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
| 970 | region_id, region_start, region_size); | ||
| 971 | } | ||
| 972 | |||
| 973 | out: | ||
| 974 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 975 | return result; | ||
| 976 | } | ||
| 977 | |||
| 978 | static int dump_device_info(struct ps3_repository_device *repo, | ||
| 979 | unsigned int num_dev) | ||
| 980 | { | ||
| 981 | int result = 0; | ||
| 982 | |||
| 983 | pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); | ||
| 984 | |||
| 985 | for (repo->dev_index = 0; repo->dev_index < num_dev; | ||
| 986 | repo->dev_index++) { | ||
| 987 | |||
| 988 | result = ps3_repository_read_dev_type(repo->bus_index, | ||
| 989 | repo->dev_index, &repo->dev_type); | ||
| 990 | |||
| 991 | if (result) { | ||
| 992 | pr_debug("%s:%d ps3_repository_read_dev_type" | ||
| 993 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 994 | repo->bus_index, repo->dev_index); | ||
| 995 | break; | ||
| 996 | } | ||
| 997 | |||
| 998 | result = ps3_repository_read_dev_id(repo->bus_index, | ||
| 999 | repo->dev_index, &repo->dev_id); | ||
| 1000 | |||
| 1001 | if (result) { | ||
| 1002 | pr_debug("%s:%d ps3_repository_read_dev_id" | ||
| 1003 | " (%u:%u) failed\n", __func__, __LINE__, | ||
| 1004 | repo->bus_index, repo->dev_index); | ||
| 1005 | continue; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | ||
| 1009 | __LINE__, repo->bus_index, repo->dev_index, | ||
| 1010 | repo->dev_type, repo->dev_id); | ||
| 1011 | |||
| 1012 | ps3_repository_dump_resource_info(repo); | ||
| 1013 | |||
| 1014 | if (repo->bus_type == PS3_BUS_TYPE_STORAGE) | ||
| 1015 | dump_stor_dev_info(repo); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 1019 | return result; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | int ps3_repository_dump_bus_info(void) | ||
| 1023 | { | ||
| 1024 | int result = 0; | ||
| 1025 | struct ps3_repository_device repo; | ||
| 1026 | |||
| 1027 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 1028 | |||
| 1029 | memset(&repo, 0, sizeof(repo)); | ||
| 1030 | |||
| 1031 | for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { | ||
| 1032 | unsigned int num_dev; | ||
| 1033 | |||
| 1034 | result = ps3_repository_read_bus_type(repo.bus_index, | ||
| 1035 | &repo.bus_type); | ||
| 1036 | |||
| 1037 | if (result) { | ||
| 1038 | pr_debug("%s:%d read_bus_type(%u) failed\n", | ||
| 1039 | __func__, __LINE__, repo.bus_index); | ||
| 1040 | break; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | result = ps3_repository_read_bus_id(repo.bus_index, | ||
| 1044 | &repo.bus_id); | ||
| 1045 | |||
| 1046 | if (result) { | ||
| 1047 | pr_debug("%s:%d read_bus_id(%u) failed\n", | ||
| 1048 | __func__, __LINE__, repo.bus_index); | ||
| 1049 | continue; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | if (repo.bus_index != repo.bus_id) | ||
| 1053 | pr_debug("%s:%d bus_index != bus_id\n", | ||
| 1054 | __func__, __LINE__); | ||
| 1055 | |||
| 1056 | result = ps3_repository_read_bus_num_dev(repo.bus_index, | ||
| 1057 | &num_dev); | ||
| 1058 | |||
| 1059 | if (result) { | ||
| 1060 | pr_debug("%s:%d read_bus_num_dev(%u) failed\n", | ||
| 1061 | __func__, __LINE__, repo.bus_index); | ||
| 1062 | continue; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | ||
| 1066 | __func__, __LINE__, repo.bus_index, repo.bus_type, | ||
| 1067 | repo.bus_id, num_dev); | ||
| 1068 | |||
| 1069 | dump_device_info(&repo, num_dev); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 1073 | return result; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | #endif /* defined(DEBUG) */ | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 935396766621..aa05288de64e 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
| @@ -37,27 +37,35 @@ | |||
| 37 | #include "platform.h" | 37 | #include "platform.h" |
| 38 | 38 | ||
| 39 | #if defined(DEBUG) | 39 | #if defined(DEBUG) |
| 40 | #define DBG(fmt...) udbg_printf(fmt) | 40 | #define DBG udbg_printf |
| 41 | #else | 41 | #else |
| 42 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 42 | #define DBG pr_debug |
| 43 | #endif | 43 | #endif |
| 44 | 44 | ||
| 45 | #if !defined(CONFIG_SMP) | 45 | #if !defined(CONFIG_SMP) |
| 46 | static void smp_send_stop(void) {} | 46 | static void smp_send_stop(void) {} |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| 49 | int ps3_get_firmware_version(union ps3_firmware_version *v) | 49 | static union ps3_firmware_version ps3_firmware_version; |
| 50 | |||
| 51 | void ps3_get_firmware_version(union ps3_firmware_version *v) | ||
| 50 | { | 52 | { |
| 51 | int result = lv1_get_version_info(&v->raw); | 53 | *v = ps3_firmware_version; |
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); | ||
| 52 | 56 | ||
| 53 | if (result) { | 57 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev) |
| 54 | v->raw = 0; | 58 | { |
| 55 | return -1; | 59 | union ps3_firmware_version x; |
| 56 | } | 60 | |
| 61 | x.pad = 0; | ||
| 62 | x.major = major; | ||
| 63 | x.minor = minor; | ||
| 64 | x.rev = rev; | ||
| 57 | 65 | ||
| 58 | return result; | 66 | return (ps3_firmware_version.raw - x.raw); |
| 59 | } | 67 | } |
| 60 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); | 68 | EXPORT_SYMBOL_GPL(ps3_compare_firmware_version); |
| 61 | 69 | ||
| 62 | static void ps3_power_save(void) | 70 | static void ps3_power_save(void) |
| 63 | { | 71 | { |
| @@ -99,7 +107,8 @@ static void ps3_panic(char *str) | |||
| 99 | while(1); | 107 | while(1); |
| 100 | } | 108 | } |
| 101 | 109 | ||
| 102 | #ifdef CONFIG_FB_PS3 | 110 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ |
| 111 | defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | ||
| 103 | static void prealloc(struct ps3_prealloc *p) | 112 | static void prealloc(struct ps3_prealloc *p) |
| 104 | { | 113 | { |
| 105 | if (!p->size) | 114 | if (!p->size) |
| @@ -115,12 +124,15 @@ static void prealloc(struct ps3_prealloc *p) | |||
| 115 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, | 124 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, |
| 116 | p->address); | 125 | p->address); |
| 117 | } | 126 | } |
| 127 | #endif | ||
| 118 | 128 | ||
| 129 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) | ||
| 119 | struct ps3_prealloc ps3fb_videomemory = { | 130 | struct ps3_prealloc ps3fb_videomemory = { |
| 120 | .name = "ps3fb videomemory", | 131 | .name = "ps3fb videomemory", |
| 121 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, | 132 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, |
| 122 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ | 133 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ |
| 123 | }; | 134 | }; |
| 135 | EXPORT_SYMBOL_GPL(ps3fb_videomemory); | ||
| 124 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) | 136 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) |
| 125 | 137 | ||
| 126 | static int __init early_parse_ps3fb(char *p) | 138 | static int __init early_parse_ps3fb(char *p) |
| @@ -137,6 +149,30 @@ early_param("ps3fb", early_parse_ps3fb); | |||
| 137 | #define prealloc_ps3fb_videomemory() do { } while (0) | 149 | #define prealloc_ps3fb_videomemory() do { } while (0) |
| 138 | #endif | 150 | #endif |
| 139 | 151 | ||
| 152 | #if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | ||
| 153 | struct ps3_prealloc ps3flash_bounce_buffer = { | ||
| 154 | .name = "ps3flash bounce buffer", | ||
| 155 | .size = 256*1024, | ||
| 156 | .align = 256*1024 | ||
| 157 | }; | ||
| 158 | EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer); | ||
| 159 | #define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer) | ||
| 160 | |||
| 161 | static int __init early_parse_ps3flash(char *p) | ||
| 162 | { | ||
| 163 | if (!p) | ||
| 164 | return 1; | ||
| 165 | |||
| 166 | if (!strcmp(p, "off")) | ||
| 167 | ps3flash_bounce_buffer.size = 0; | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | early_param("ps3flash", early_parse_ps3flash); | ||
| 172 | #else | ||
| 173 | #define prealloc_ps3flash_bounce_buffer() do { } while (0) | ||
| 174 | #endif | ||
| 175 | |||
| 140 | static int ps3_set_dabr(u64 dabr) | 176 | static int ps3_set_dabr(u64 dabr) |
| 141 | { | 177 | { |
| 142 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; | 178 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; |
| @@ -146,13 +182,13 @@ static int ps3_set_dabr(u64 dabr) | |||
| 146 | 182 | ||
| 147 | static void __init ps3_setup_arch(void) | 183 | static void __init ps3_setup_arch(void) |
| 148 | { | 184 | { |
| 149 | union ps3_firmware_version v; | ||
| 150 | 185 | ||
| 151 | DBG(" -> %s:%d\n", __func__, __LINE__); | 186 | DBG(" -> %s:%d\n", __func__, __LINE__); |
| 152 | 187 | ||
| 153 | ps3_get_firmware_version(&v); | 188 | lv1_get_version_info(&ps3_firmware_version.raw); |
| 154 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor, | 189 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", |
| 155 | v.rev); | 190 | ps3_firmware_version.major, ps3_firmware_version.minor, |
| 191 | ps3_firmware_version.rev); | ||
| 156 | 192 | ||
| 157 | ps3_spu_set_platform(); | 193 | ps3_spu_set_platform(); |
| 158 | ps3_map_htab(); | 194 | ps3_map_htab(); |
| @@ -166,6 +202,8 @@ static void __init ps3_setup_arch(void) | |||
| 166 | #endif | 202 | #endif |
| 167 | 203 | ||
| 168 | prealloc_ps3fb_videomemory(); | 204 | prealloc_ps3fb_videomemory(); |
| 205 | prealloc_ps3flash_bounce_buffer(); | ||
| 206 | |||
| 169 | ppc_md.power_save = ps3_power_save; | 207 | ppc_md.power_save = ps3_power_save; |
| 170 | 208 | ||
| 171 | DBG(" <- %s:%d\n", __func__, __LINE__); | 209 | DBG(" <- %s:%d\n", __func__, __LINE__); |
| @@ -184,7 +222,7 @@ static int __init ps3_probe(void) | |||
| 184 | DBG(" -> %s:%d\n", __func__, __LINE__); | 222 | DBG(" -> %s:%d\n", __func__, __LINE__); |
| 185 | 223 | ||
| 186 | dt_root = of_get_flat_dt_root(); | 224 | dt_root = of_get_flat_dt_root(); |
| 187 | if (!of_flat_dt_is_compatible(dt_root, "PS3")) | 225 | if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) |
| 188 | return 0; | 226 | return 0; |
| 189 | 227 | ||
| 190 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | 228 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; |
| @@ -201,31 +239,12 @@ static int __init ps3_probe(void) | |||
| 201 | #if defined(CONFIG_KEXEC) | 239 | #if defined(CONFIG_KEXEC) |
| 202 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) | 240 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) |
| 203 | { | 241 | { |
| 204 | DBG(" -> %s:%d\n", __func__, __LINE__); | 242 | int cpu = smp_processor_id(); |
| 205 | |||
| 206 | if (secondary) { | ||
| 207 | int cpu; | ||
| 208 | for_each_online_cpu(cpu) | ||
| 209 | if (cpu) | ||
| 210 | ps3_smp_cleanup_cpu(cpu); | ||
| 211 | } else | ||
| 212 | ps3_smp_cleanup_cpu(0); | ||
| 213 | |||
| 214 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
| 215 | } | ||
| 216 | |||
| 217 | static void ps3_machine_kexec(struct kimage *image) | ||
| 218 | { | ||
| 219 | unsigned long ppe_id; | ||
| 220 | |||
| 221 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
| 222 | 243 | ||
| 223 | lv1_get_logical_ppe_id(&ppe_id); | 244 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
| 224 | lv1_configure_irq_state_bitmap(ppe_id, 0, 0); | ||
| 225 | ps3_mm_shutdown(); | ||
| 226 | ps3_mm_vas_destroy(); | ||
| 227 | 245 | ||
| 228 | default_machine_kexec(image); | 246 | ps3_smp_cleanup_cpu(cpu); |
| 247 | ps3_shutdown_IRQ(cpu); | ||
| 229 | 248 | ||
| 230 | DBG(" <- %s:%d\n", __func__, __LINE__); | 249 | DBG(" <- %s:%d\n", __func__, __LINE__); |
| 231 | } | 250 | } |
| @@ -247,7 +266,7 @@ define_machine(ps3) { | |||
| 247 | .power_off = ps3_power_off, | 266 | .power_off = ps3_power_off, |
| 248 | #if defined(CONFIG_KEXEC) | 267 | #if defined(CONFIG_KEXEC) |
| 249 | .kexec_cpu_down = ps3_kexec_cpu_down, | 268 | .kexec_cpu_down = ps3_kexec_cpu_down, |
| 250 | .machine_kexec = ps3_machine_kexec, | 269 | .machine_kexec = default_machine_kexec, |
| 251 | .machine_kexec_prepare = default_machine_kexec_prepare, | 270 | .machine_kexec_prepare = default_machine_kexec_prepare, |
| 252 | .machine_crash_shutdown = default_machine_crash_shutdown, | 271 | .machine_crash_shutdown = default_machine_crash_shutdown, |
| 253 | #endif | 272 | #endif |
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 53416ec5198b..f0b12f212363 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c | |||
| @@ -27,9 +27,9 @@ | |||
| 27 | #include "platform.h" | 27 | #include "platform.h" |
| 28 | 28 | ||
| 29 | #if defined(DEBUG) | 29 | #if defined(DEBUG) |
| 30 | #define DBG(fmt...) udbg_printf(fmt) | 30 | #define DBG udbg_printf |
| 31 | #else | 31 | #else |
| 32 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 32 | #define DBG pr_debug |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | static irqreturn_t ipi_function_handler(int irq, void *msg) | 35 | static irqreturn_t ipi_function_handler(int irq, void *msg) |
| @@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(int irq, void *msg) | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | /** | 41 | /** |
| 42 | * virqs - a per cpu array of virqs for ipi use | 42 | * ps3_ipi_virqs - a per cpu array of virqs for ipi use |
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | #define MSG_COUNT 4 | 45 | #define MSG_COUNT 4 |
| 46 | static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]); | 46 | static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]); |
| 47 | 47 | ||
| 48 | static const char *names[MSG_COUNT] = { | 48 | static const char *names[MSG_COUNT] = { |
| 49 | "ipi call", | 49 | "ipi call", |
| @@ -62,7 +62,7 @@ static void do_message_pass(int target, int msg) | |||
| 62 | return; | 62 | return; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | virq = per_cpu(virqs, target)[msg]; | 65 | virq = per_cpu(ps3_ipi_virqs, target)[msg]; |
| 66 | result = ps3_send_event_locally(virq); | 66 | result = ps3_send_event_locally(virq); |
| 67 | 67 | ||
| 68 | if (result) | 68 | if (result) |
| @@ -94,13 +94,13 @@ static int ps3_smp_probe(void) | |||
| 94 | static void __init ps3_smp_setup_cpu(int cpu) | 94 | static void __init ps3_smp_setup_cpu(int cpu) |
| 95 | { | 95 | { |
| 96 | int result; | 96 | int result; |
| 97 | unsigned int *virqs = per_cpu(virqs, cpu); | 97 | unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); |
| 98 | int i; | 98 | int i; |
| 99 | 99 | ||
| 100 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | 100 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
| 101 | 101 | ||
| 102 | /* | 102 | /* |
| 103 | * Check assumptions on virqs[] indexing. If this | 103 | * Check assumptions on ps3_ipi_virqs[] indexing. If this |
| 104 | * check fails, then a different mapping of PPC_MSG_ | 104 | * check fails, then a different mapping of PPC_MSG_ |
| 105 | * to index needs to be setup. | 105 | * to index needs to be setup. |
| 106 | */ | 106 | */ |
| @@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int cpu) | |||
| 132 | 132 | ||
| 133 | void ps3_smp_cleanup_cpu(int cpu) | 133 | void ps3_smp_cleanup_cpu(int cpu) |
| 134 | { | 134 | { |
| 135 | unsigned int *virqs = per_cpu(virqs, cpu); | 135 | unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); |
| 136 | int i; | 136 | int i; |
| 137 | 137 | ||
| 138 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | 138 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
| 139 | 139 | ||
| 140 | for (i = 0; i < MSG_COUNT; i++) { | 140 | for (i = 0; i < MSG_COUNT; i++) { |
| 141 | free_irq(virqs[i], (void*)(long)i); | 141 | /* Can't call free_irq from interrupt context. */ |
| 142 | ps3_event_receive_port_destroy(virqs[i]); | 142 | ps3_event_receive_port_destroy(virqs[i]); |
| 143 | virqs[i] = NO_IRQ; | 143 | virqs[i] = NO_IRQ; |
| 144 | } | 144 | } |
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index 651437cb2c18..c7f734c89462 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c | |||
| @@ -182,15 +182,18 @@ static int __init setup_areas(struct spu *spu) | |||
| 182 | { | 182 | { |
| 183 | struct table {char* name; unsigned long addr; unsigned long size;}; | 183 | struct table {char* name; unsigned long addr; unsigned long size;}; |
| 184 | 184 | ||
| 185 | spu_pdata(spu)->shadow = __ioremap( | 185 | spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr, |
| 186 | spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), | 186 | sizeof(struct spe_shadow), |
| 187 | pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED); | 187 | pgprot_val(PAGE_READONLY) | |
| 188 | _PAGE_NO_CACHE); | ||
| 188 | if (!spu_pdata(spu)->shadow) { | 189 | if (!spu_pdata(spu)->shadow) { |
| 189 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); | 190 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); |
| 190 | goto fail_ioremap; | 191 | goto fail_ioremap; |
| 191 | } | 192 | } |
| 192 | 193 | ||
| 193 | spu->local_store = ioremap(spu->local_store_phys, LS_SIZE); | 194 | spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys, |
| 195 | LS_SIZE, _PAGE_NO_CACHE); | ||
| 196 | |||
| 194 | if (!spu->local_store) { | 197 | if (!spu->local_store) { |
| 195 | pr_debug("%s:%d: ioremap local_store failed\n", | 198 | pr_debug("%s:%d: ioremap local_store failed\n", |
| 196 | __func__, __LINE__); | 199 | __func__, __LINE__); |
| @@ -199,6 +202,7 @@ static int __init setup_areas(struct spu *spu) | |||
| 199 | 202 | ||
| 200 | spu->problem = ioremap(spu->problem_phys, | 203 | spu->problem = ioremap(spu->problem_phys, |
| 201 | sizeof(struct spu_problem)); | 204 | sizeof(struct spu_problem)); |
| 205 | |||
| 202 | if (!spu->problem) { | 206 | if (!spu->problem) { |
| 203 | pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); | 207 | pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); |
| 204 | goto fail_ioremap; | 208 | goto fail_ioremap; |
| @@ -206,6 +210,7 @@ static int __init setup_areas(struct spu *spu) | |||
| 206 | 210 | ||
| 207 | spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, | 211 | spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, |
| 208 | sizeof(struct spu_priv2)); | 212 | sizeof(struct spu_priv2)); |
| 213 | |||
| 209 | if (!spu->priv2) { | 214 | if (!spu->priv2) { |
| 210 | pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); | 215 | pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); |
| 211 | goto fail_ioremap; | 216 | goto fail_ioremap; |
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 6bda51027cc6..4bb634a17e43 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
| @@ -30,22 +30,228 @@ | |||
| 30 | 30 | ||
| 31 | #include "platform.h" | 31 | #include "platform.h" |
| 32 | 32 | ||
| 33 | static struct device ps3_system_bus = { | ||
| 34 | .bus_id = "ps3_system", | ||
| 35 | }; | ||
| 36 | |||
| 37 | /* FIXME: need device usage counters! */ | ||
| 38 | struct { | ||
| 39 | struct mutex mutex; | ||
| 40 | int sb_11; /* usb 0 */ | ||
| 41 | int sb_12; /* usb 0 */ | ||
| 42 | int gpu; | ||
| 43 | } static usage_hack; | ||
| 44 | |||
| 45 | static int ps3_is_device(struct ps3_system_bus_device *dev, | ||
| 46 | unsigned int bus_id, unsigned int dev_id) | ||
| 47 | { | ||
| 48 | return dev->bus_id == bus_id && dev->dev_id == dev_id; | ||
| 49 | } | ||
| 50 | |||
| 51 | static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev) | ||
| 52 | { | ||
| 53 | int result; | ||
| 54 | |||
| 55 | BUG_ON(!dev->bus_id); | ||
| 56 | mutex_lock(&usage_hack.mutex); | ||
| 57 | |||
| 58 | if (ps3_is_device(dev, 1, 1)) { | ||
| 59 | usage_hack.sb_11++; | ||
| 60 | if (usage_hack.sb_11 > 1) { | ||
| 61 | result = 0; | ||
| 62 | goto done; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | if (ps3_is_device(dev, 1, 2)) { | ||
| 67 | usage_hack.sb_12++; | ||
| 68 | if (usage_hack.sb_12 > 1) { | ||
| 69 | result = 0; | ||
| 70 | goto done; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | result = lv1_open_device(dev->bus_id, dev->dev_id, 0); | ||
| 75 | |||
| 76 | if (result) { | ||
| 77 | pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__, | ||
| 78 | __LINE__, ps3_result(result)); | ||
| 79 | result = -EPERM; | ||
| 80 | } | ||
| 81 | |||
| 82 | done: | ||
| 83 | mutex_unlock(&usage_hack.mutex); | ||
| 84 | return result; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev) | ||
| 88 | { | ||
| 89 | int result; | ||
| 90 | |||
| 91 | BUG_ON(!dev->bus_id); | ||
| 92 | mutex_lock(&usage_hack.mutex); | ||
| 93 | |||
| 94 | if (ps3_is_device(dev, 1, 1)) { | ||
| 95 | usage_hack.sb_11--; | ||
| 96 | if (usage_hack.sb_11) { | ||
| 97 | result = 0; | ||
| 98 | goto done; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | if (ps3_is_device(dev, 1, 2)) { | ||
| 103 | usage_hack.sb_12--; | ||
| 104 | if (usage_hack.sb_12) { | ||
| 105 | result = 0; | ||
| 106 | goto done; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | result = lv1_close_device(dev->bus_id, dev->dev_id); | ||
| 111 | BUG_ON(result); | ||
| 112 | |||
| 113 | done: | ||
| 114 | mutex_unlock(&usage_hack.mutex); | ||
| 115 | return result; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev) | ||
| 119 | { | ||
| 120 | int result; | ||
| 121 | |||
| 122 | mutex_lock(&usage_hack.mutex); | ||
| 123 | |||
| 124 | usage_hack.gpu++; | ||
| 125 | if (usage_hack.gpu > 1) { | ||
| 126 | result = 0; | ||
| 127 | goto done; | ||
| 128 | } | ||
| 129 | |||
| 130 | result = lv1_gpu_open(0); | ||
| 131 | |||
| 132 | if (result) { | ||
| 133 | pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__, | ||
| 134 | __LINE__, ps3_result(result)); | ||
| 135 | result = -EPERM; | ||
| 136 | } | ||
| 137 | |||
| 138 | done: | ||
| 139 | mutex_unlock(&usage_hack.mutex); | ||
| 140 | return result; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev) | ||
| 144 | { | ||
| 145 | int result; | ||
| 146 | |||
| 147 | mutex_lock(&usage_hack.mutex); | ||
| 148 | |||
| 149 | usage_hack.gpu--; | ||
| 150 | if (usage_hack.gpu) { | ||
| 151 | result = 0; | ||
| 152 | goto done; | ||
| 153 | } | ||
| 154 | |||
| 155 | result = lv1_gpu_close(); | ||
| 156 | BUG_ON(result); | ||
| 157 | |||
| 158 | done: | ||
| 159 | mutex_unlock(&usage_hack.mutex); | ||
| 160 | return result; | ||
| 161 | } | ||
| 162 | |||
| 163 | int ps3_open_hv_device(struct ps3_system_bus_device *dev) | ||
| 164 | { | ||
| 165 | BUG_ON(!dev); | ||
| 166 | pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); | ||
| 167 | |||
| 168 | switch (dev->match_id) { | ||
| 169 | case PS3_MATCH_ID_EHCI: | ||
| 170 | case PS3_MATCH_ID_OHCI: | ||
| 171 | case PS3_MATCH_ID_GELIC: | ||
| 172 | case PS3_MATCH_ID_STOR_DISK: | ||
| 173 | case PS3_MATCH_ID_STOR_ROM: | ||
| 174 | case PS3_MATCH_ID_STOR_FLASH: | ||
| 175 | return ps3_open_hv_device_sb(dev); | ||
| 176 | |||
| 177 | case PS3_MATCH_ID_SOUND: | ||
| 178 | case PS3_MATCH_ID_GRAPHICS: | ||
| 179 | return ps3_open_hv_device_gpu(dev); | ||
| 180 | |||
| 181 | case PS3_MATCH_ID_AV_SETTINGS: | ||
| 182 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
| 183 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | ||
| 184 | __LINE__, dev->match_id); | ||
| 185 | pr_debug("%s:%d: bus_id: %u\n", __func__, | ||
| 186 | __LINE__, dev->bus_id); | ||
| 187 | BUG(); | ||
| 188 | return -EINVAL; | ||
| 189 | |||
| 190 | default: | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | |||
| 194 | pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, | ||
| 195 | dev->match_id); | ||
| 196 | BUG(); | ||
| 197 | return -ENODEV; | ||
| 198 | } | ||
| 199 | EXPORT_SYMBOL_GPL(ps3_open_hv_device); | ||
| 200 | |||
| 201 | int ps3_close_hv_device(struct ps3_system_bus_device *dev) | ||
| 202 | { | ||
| 203 | BUG_ON(!dev); | ||
| 204 | pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); | ||
| 205 | |||
| 206 | switch (dev->match_id) { | ||
| 207 | case PS3_MATCH_ID_EHCI: | ||
| 208 | case PS3_MATCH_ID_OHCI: | ||
| 209 | case PS3_MATCH_ID_GELIC: | ||
| 210 | case PS3_MATCH_ID_STOR_DISK: | ||
| 211 | case PS3_MATCH_ID_STOR_ROM: | ||
| 212 | case PS3_MATCH_ID_STOR_FLASH: | ||
| 213 | return ps3_close_hv_device_sb(dev); | ||
| 214 | |||
| 215 | case PS3_MATCH_ID_SOUND: | ||
| 216 | case PS3_MATCH_ID_GRAPHICS: | ||
| 217 | return ps3_close_hv_device_gpu(dev); | ||
| 218 | |||
| 219 | case PS3_MATCH_ID_AV_SETTINGS: | ||
| 220 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
| 221 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | ||
| 222 | __LINE__, dev->match_id); | ||
| 223 | pr_debug("%s:%d: bus_id: %u\n", __func__, | ||
| 224 | __LINE__, dev->bus_id); | ||
| 225 | BUG(); | ||
| 226 | return -EINVAL; | ||
| 227 | |||
| 228 | default: | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | |||
| 232 | pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, | ||
| 233 | dev->match_id); | ||
| 234 | BUG(); | ||
| 235 | return -ENODEV; | ||
| 236 | } | ||
| 237 | EXPORT_SYMBOL_GPL(ps3_close_hv_device); | ||
| 238 | |||
| 33 | #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) | 239 | #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) |
| 34 | static void _dump_mmio_region(const struct ps3_mmio_region* r, | 240 | static void _dump_mmio_region(const struct ps3_mmio_region* r, |
| 35 | const char* func, int line) | 241 | const char* func, int line) |
| 36 | { | 242 | { |
| 37 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | 243 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, |
| 38 | r->did.dev_id); | 244 | r->dev->dev_id); |
| 39 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 245 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
| 40 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); | 246 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); |
| 41 | pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); | 247 | pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); |
| 42 | } | 248 | } |
| 43 | 249 | ||
| 44 | int ps3_mmio_region_create(struct ps3_mmio_region *r) | 250 | static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r) |
| 45 | { | 251 | { |
| 46 | int result; | 252 | int result; |
| 47 | 253 | ||
| 48 | result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id, | 254 | result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id, |
| 49 | r->bus_addr, r->len, r->page_size, &r->lpar_addr); | 255 | r->bus_addr, r->len, r->page_size, &r->lpar_addr); |
| 50 | 256 | ||
| 51 | if (result) { | 257 | if (result) { |
| @@ -57,13 +263,26 @@ int ps3_mmio_region_create(struct ps3_mmio_region *r) | |||
| 57 | dump_mmio_region(r); | 263 | dump_mmio_region(r); |
| 58 | return result; | 264 | return result; |
| 59 | } | 265 | } |
| 266 | |||
| 267 | static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r) | ||
| 268 | { | ||
| 269 | /* device specific; do nothing currently */ | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | int ps3_mmio_region_create(struct ps3_mmio_region *r) | ||
| 274 | { | ||
| 275 | return r->mmio_ops->create(r); | ||
| 276 | } | ||
| 60 | EXPORT_SYMBOL_GPL(ps3_mmio_region_create); | 277 | EXPORT_SYMBOL_GPL(ps3_mmio_region_create); |
| 61 | 278 | ||
| 62 | int ps3_free_mmio_region(struct ps3_mmio_region *r) | 279 | static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) |
| 63 | { | 280 | { |
| 64 | int result; | 281 | int result; |
| 65 | 282 | ||
| 66 | result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id, | 283 | dump_mmio_region(r); |
| 284 | ; | ||
| 285 | result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, | ||
| 67 | r->lpar_addr); | 286 | r->lpar_addr); |
| 68 | 287 | ||
| 69 | if (result) | 288 | if (result) |
| @@ -73,14 +292,60 @@ int ps3_free_mmio_region(struct ps3_mmio_region *r) | |||
| 73 | r->lpar_addr = 0; | 292 | r->lpar_addr = 0; |
| 74 | return result; | 293 | return result; |
| 75 | } | 294 | } |
| 295 | |||
| 296 | static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r) | ||
| 297 | { | ||
| 298 | /* device specific; do nothing currently */ | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | |||
| 303 | int ps3_free_mmio_region(struct ps3_mmio_region *r) | ||
| 304 | { | ||
| 305 | return r->mmio_ops->free(r); | ||
| 306 | } | ||
| 307 | |||
| 76 | EXPORT_SYMBOL_GPL(ps3_free_mmio_region); | 308 | EXPORT_SYMBOL_GPL(ps3_free_mmio_region); |
| 77 | 309 | ||
| 310 | static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = { | ||
| 311 | .create = ps3_sb_mmio_region_create, | ||
| 312 | .free = ps3_sb_free_mmio_region | ||
| 313 | }; | ||
| 314 | |||
| 315 | static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = { | ||
| 316 | .create = ps3_ioc0_mmio_region_create, | ||
| 317 | .free = ps3_ioc0_free_mmio_region | ||
| 318 | }; | ||
| 319 | |||
| 320 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, | ||
| 321 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, | ||
| 322 | enum ps3_mmio_page_size page_size) | ||
| 323 | { | ||
| 324 | r->dev = dev; | ||
| 325 | r->bus_addr = bus_addr; | ||
| 326 | r->len = len; | ||
| 327 | r->page_size = page_size; | ||
| 328 | switch (dev->dev_type) { | ||
| 329 | case PS3_DEVICE_TYPE_SB: | ||
| 330 | r->mmio_ops = &ps3_mmio_sb_region_ops; | ||
| 331 | break; | ||
| 332 | case PS3_DEVICE_TYPE_IOC0: | ||
| 333 | r->mmio_ops = &ps3_mmio_ioc0_region_ops; | ||
| 334 | break; | ||
| 335 | default: | ||
| 336 | BUG(); | ||
| 337 | return -EINVAL; | ||
| 338 | } | ||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | EXPORT_SYMBOL_GPL(ps3_mmio_region_init); | ||
| 342 | |||
| 78 | static int ps3_system_bus_match(struct device *_dev, | 343 | static int ps3_system_bus_match(struct device *_dev, |
| 79 | struct device_driver *_drv) | 344 | struct device_driver *_drv) |
| 80 | { | 345 | { |
| 81 | int result; | 346 | int result; |
| 82 | struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv); | 347 | struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv); |
| 83 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 348 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 84 | 349 | ||
| 85 | result = dev->match_id == drv->match_id; | 350 | result = dev->match_id == drv->match_id; |
| 86 | 351 | ||
| @@ -92,32 +357,14 @@ static int ps3_system_bus_match(struct device *_dev, | |||
| 92 | 357 | ||
| 93 | static int ps3_system_bus_probe(struct device *_dev) | 358 | static int ps3_system_bus_probe(struct device *_dev) |
| 94 | { | 359 | { |
| 95 | int result; | 360 | int result = 0; |
| 96 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 361 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 97 | struct ps3_system_bus_driver *drv = | 362 | struct ps3_system_bus_driver *drv; |
| 98 | to_ps3_system_bus_driver(_dev->driver); | ||
| 99 | |||
| 100 | result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0); | ||
| 101 | |||
| 102 | if (result) { | ||
| 103 | pr_debug("%s:%d: lv1_open_device failed (%d)\n", | ||
| 104 | __func__, __LINE__, result); | ||
| 105 | result = -EACCES; | ||
| 106 | goto clean_none; | ||
| 107 | } | ||
| 108 | |||
| 109 | if (dev->d_region->did.bus_id) { | ||
| 110 | result = ps3_dma_region_create(dev->d_region); | ||
| 111 | 363 | ||
| 112 | if (result) { | 364 | BUG_ON(!dev); |
| 113 | pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n", | 365 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); |
| 114 | __func__, __LINE__, result); | ||
| 115 | BUG_ON("check region type"); | ||
| 116 | result = -EINVAL; | ||
| 117 | goto clean_device; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | 366 | ||
| 367 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
| 121 | BUG_ON(!drv); | 368 | BUG_ON(!drv); |
| 122 | 369 | ||
| 123 | if (drv->probe) | 370 | if (drv->probe) |
| @@ -126,56 +373,127 @@ static int ps3_system_bus_probe(struct device *_dev) | |||
| 126 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, | 373 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, |
| 127 | dev->core.bus_id); | 374 | dev->core.bus_id); |
| 128 | 375 | ||
| 129 | if (result) { | 376 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); |
| 130 | pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__); | ||
| 131 | goto clean_dma; | ||
| 132 | } | ||
| 133 | |||
| 134 | return result; | ||
| 135 | |||
| 136 | clean_dma: | ||
| 137 | ps3_dma_region_free(dev->d_region); | ||
| 138 | clean_device: | ||
| 139 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | ||
| 140 | clean_none: | ||
| 141 | return result; | 377 | return result; |
| 142 | } | 378 | } |
| 143 | 379 | ||
| 144 | static int ps3_system_bus_remove(struct device *_dev) | 380 | static int ps3_system_bus_remove(struct device *_dev) |
| 145 | { | 381 | { |
| 146 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 382 | int result = 0; |
| 147 | struct ps3_system_bus_driver *drv = | 383 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 148 | to_ps3_system_bus_driver(_dev->driver); | 384 | struct ps3_system_bus_driver *drv; |
| 385 | |||
| 386 | BUG_ON(!dev); | ||
| 387 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); | ||
| 388 | |||
| 389 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
| 390 | BUG_ON(!drv); | ||
| 149 | 391 | ||
| 150 | if (drv->remove) | 392 | if (drv->remove) |
| 151 | drv->remove(dev); | 393 | result = drv->remove(dev); |
| 152 | else | 394 | else |
| 153 | pr_info("%s:%d: %s no remove method\n", __func__, __LINE__, | 395 | dev_dbg(&dev->core, "%s:%d %s: no remove method\n", |
| 154 | dev->core.bus_id); | 396 | __func__, __LINE__, drv->core.name); |
| 397 | |||
| 398 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); | ||
| 399 | return result; | ||
| 400 | } | ||
| 401 | |||
| 402 | static void ps3_system_bus_shutdown(struct device *_dev) | ||
| 403 | { | ||
| 404 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
| 405 | struct ps3_system_bus_driver *drv; | ||
| 406 | |||
| 407 | BUG_ON(!dev); | ||
| 408 | |||
| 409 | dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, | ||
| 410 | dev->match_id); | ||
| 411 | |||
| 412 | if (!dev->core.driver) { | ||
| 413 | dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, | ||
| 414 | __LINE__); | ||
| 415 | return; | ||
| 416 | } | ||
| 417 | |||
| 418 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
| 419 | |||
| 420 | BUG_ON(!drv); | ||
| 421 | |||
| 422 | dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__, | ||
| 423 | dev->core.bus_id, drv->core.name); | ||
| 424 | |||
| 425 | if (drv->shutdown) | ||
| 426 | drv->shutdown(dev); | ||
| 427 | else if (drv->remove) { | ||
| 428 | dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n", | ||
| 429 | __func__, __LINE__, drv->core.name); | ||
| 430 | drv->remove(dev); | ||
| 431 | } else { | ||
| 432 | dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n", | ||
| 433 | __func__, __LINE__, drv->core.name); | ||
| 434 | BUG(); | ||
| 435 | } | ||
| 436 | |||
| 437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int ps3_system_bus_uevent(struct device *_dev, char **envp, | ||
| 441 | int num_envp, char *buffer, int buffer_size) | ||
| 442 | { | ||
| 443 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
| 444 | int i = 0, length = 0; | ||
| 155 | 445 | ||
| 156 | ps3_dma_region_free(dev->d_region); | 446 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, |
| 157 | ps3_free_mmio_region(dev->m_region); | 447 | &length, "MODALIAS=ps3:%d", |
| 158 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | 448 | dev->match_id)) |
| 449 | return -ENOMEM; | ||
| 159 | 450 | ||
| 451 | envp[i] = NULL; | ||
| 160 | return 0; | 452 | return 0; |
| 161 | } | 453 | } |
| 162 | 454 | ||
| 455 | static ssize_t modalias_show(struct device *_dev, struct device_attribute *a, | ||
| 456 | char *buf) | ||
| 457 | { | ||
| 458 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
| 459 | int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id); | ||
| 460 | |||
| 461 | return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; | ||
| 462 | } | ||
| 463 | |||
| 464 | static struct device_attribute ps3_system_bus_dev_attrs[] = { | ||
| 465 | __ATTR_RO(modalias), | ||
| 466 | __ATTR_NULL, | ||
| 467 | }; | ||
| 468 | |||
| 163 | struct bus_type ps3_system_bus_type = { | 469 | struct bus_type ps3_system_bus_type = { |
| 164 | .name = "ps3_system_bus", | 470 | .name = "ps3_system_bus", |
| 165 | .match = ps3_system_bus_match, | 471 | .match = ps3_system_bus_match, |
| 472 | .uevent = ps3_system_bus_uevent, | ||
| 166 | .probe = ps3_system_bus_probe, | 473 | .probe = ps3_system_bus_probe, |
| 167 | .remove = ps3_system_bus_remove, | 474 | .remove = ps3_system_bus_remove, |
| 475 | .shutdown = ps3_system_bus_shutdown, | ||
| 476 | .dev_attrs = ps3_system_bus_dev_attrs, | ||
| 168 | }; | 477 | }; |
| 169 | 478 | ||
| 170 | int __init ps3_system_bus_init(void) | 479 | static int __init ps3_system_bus_init(void) |
| 171 | { | 480 | { |
| 172 | int result; | 481 | int result; |
| 173 | 482 | ||
| 174 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | 483 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) |
| 175 | return -ENODEV; | 484 | return -ENODEV; |
| 176 | 485 | ||
| 486 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 487 | |||
| 488 | mutex_init(&usage_hack.mutex); | ||
| 489 | |||
| 490 | result = device_register(&ps3_system_bus); | ||
| 491 | BUG_ON(result); | ||
| 492 | |||
| 177 | result = bus_register(&ps3_system_bus_type); | 493 | result = bus_register(&ps3_system_bus_type); |
| 178 | BUG_ON(result); | 494 | BUG_ON(result); |
| 495 | |||
| 496 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 179 | return result; | 497 | return result; |
| 180 | } | 498 | } |
| 181 | 499 | ||
| @@ -185,16 +503,13 @@ core_initcall(ps3_system_bus_init); | |||
| 185 | * Returns the virtual address of the buffer and sets dma_handle | 503 | * Returns the virtual address of the buffer and sets dma_handle |
| 186 | * to the dma address (mapping) of the first page. | 504 | * to the dma address (mapping) of the first page. |
| 187 | */ | 505 | */ |
| 188 | |||
| 189 | static void * ps3_alloc_coherent(struct device *_dev, size_t size, | 506 | static void * ps3_alloc_coherent(struct device *_dev, size_t size, |
| 190 | dma_addr_t *dma_handle, gfp_t flag) | 507 | dma_addr_t *dma_handle, gfp_t flag) |
| 191 | { | 508 | { |
| 192 | int result; | 509 | int result; |
| 193 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 510 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 194 | unsigned long virt_addr; | 511 | unsigned long virt_addr; |
| 195 | 512 | ||
| 196 | BUG_ON(!dev->d_region->bus_addr); | ||
| 197 | |||
| 198 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); | 513 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); |
| 199 | flag |= __GFP_ZERO; | 514 | flag |= __GFP_ZERO; |
| 200 | 515 | ||
| @@ -205,7 +520,8 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size, | |||
| 205 | goto clean_none; | 520 | goto clean_none; |
| 206 | } | 521 | } |
| 207 | 522 | ||
| 208 | result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle); | 523 | result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle, |
| 524 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); | ||
| 209 | 525 | ||
| 210 | if (result) { | 526 | if (result) { |
| 211 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 527 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
| @@ -226,7 +542,7 @@ clean_none: | |||
| 226 | static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | 542 | static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, |
| 227 | dma_addr_t dma_handle) | 543 | dma_addr_t dma_handle) |
| 228 | { | 544 | { |
| 229 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 545 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 230 | 546 | ||
| 231 | ps3_dma_unmap(dev->d_region, dma_handle, size); | 547 | ps3_dma_unmap(dev->d_region, dma_handle, size); |
| 232 | free_pages((unsigned long)vaddr, get_order(size)); | 548 | free_pages((unsigned long)vaddr, get_order(size)); |
| @@ -239,15 +555,16 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | |||
| 239 | * byte within the page as vaddr. | 555 | * byte within the page as vaddr. |
| 240 | */ | 556 | */ |
| 241 | 557 | ||
| 242 | static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, | 558 | static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, |
| 243 | enum dma_data_direction direction) | 559 | enum dma_data_direction direction) |
| 244 | { | 560 | { |
| 245 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 561 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 246 | int result; | 562 | int result; |
| 247 | unsigned long bus_addr; | 563 | unsigned long bus_addr; |
| 248 | 564 | ||
| 249 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, | 565 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, |
| 250 | &bus_addr); | 566 | &bus_addr, |
| 567 | IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M); | ||
| 251 | 568 | ||
| 252 | if (result) { | 569 | if (result) { |
| 253 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 570 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
| @@ -257,10 +574,44 @@ static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, | |||
| 257 | return bus_addr; | 574 | return bus_addr; |
| 258 | } | 575 | } |
| 259 | 576 | ||
| 577 | static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, | ||
| 578 | size_t size, | ||
| 579 | enum dma_data_direction direction) | ||
| 580 | { | ||
| 581 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
| 582 | int result; | ||
| 583 | unsigned long bus_addr; | ||
| 584 | u64 iopte_flag; | ||
| 585 | |||
| 586 | iopte_flag = IOPTE_M; | ||
| 587 | switch (direction) { | ||
| 588 | case DMA_BIDIRECTIONAL: | ||
| 589 | iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW; | ||
| 590 | break; | ||
| 591 | case DMA_TO_DEVICE: | ||
| 592 | iopte_flag |= IOPTE_PP_R | IOPTE_SO_R; | ||
| 593 | break; | ||
| 594 | case DMA_FROM_DEVICE: | ||
| 595 | iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW; | ||
| 596 | break; | ||
| 597 | default: | ||
| 598 | /* not happned */ | ||
| 599 | BUG(); | ||
| 600 | }; | ||
| 601 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, | ||
| 602 | &bus_addr, iopte_flag); | ||
| 603 | |||
| 604 | if (result) { | ||
| 605 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | ||
| 606 | __func__, __LINE__, result); | ||
| 607 | } | ||
| 608 | return bus_addr; | ||
| 609 | } | ||
| 610 | |||
| 260 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | 611 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, |
| 261 | size_t size, enum dma_data_direction direction) | 612 | size_t size, enum dma_data_direction direction) |
| 262 | { | 613 | { |
| 263 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 614 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 264 | int result; | 615 | int result; |
| 265 | 616 | ||
| 266 | result = ps3_dma_unmap(dev->d_region, dma_addr, size); | 617 | result = ps3_dma_unmap(dev->d_region, dma_addr, size); |
| @@ -271,20 +622,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | |||
| 271 | } | 622 | } |
| 272 | } | 623 | } |
| 273 | 624 | ||
| 274 | static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, | 625 | static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents, |
| 275 | enum dma_data_direction direction) | 626 | enum dma_data_direction direction) |
| 276 | { | 627 | { |
| 277 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 628 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
| 278 | BUG_ON("do"); | 629 | BUG_ON("do"); |
| 279 | return -EPERM; | 630 | return -EPERM; |
| 280 | #else | 631 | #else |
| 281 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 632 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 282 | int i; | 633 | int i; |
| 283 | 634 | ||
| 284 | for (i = 0; i < nents; i++, sg++) { | 635 | for (i = 0; i < nents; i++, sg++) { |
| 285 | int result = ps3_dma_map(dev->d_region, | 636 | int result = ps3_dma_map(dev->d_region, |
| 286 | page_to_phys(sg->page) + sg->offset, sg->length, | 637 | page_to_phys(sg->page) + sg->offset, sg->length, |
| 287 | &sg->dma_address); | 638 | &sg->dma_address, 0); |
| 288 | 639 | ||
| 289 | if (result) { | 640 | if (result) { |
| 290 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 641 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
| @@ -299,7 +650,15 @@ static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, | |||
| 299 | #endif | 650 | #endif |
| 300 | } | 651 | } |
| 301 | 652 | ||
| 302 | static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, | 653 | static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, |
| 654 | int nents, | ||
| 655 | enum dma_data_direction direction) | ||
| 656 | { | ||
| 657 | BUG(); | ||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, | ||
| 303 | int nents, enum dma_data_direction direction) | 662 | int nents, enum dma_data_direction direction) |
| 304 | { | 663 | { |
| 305 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 664 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
| @@ -307,18 +666,34 @@ static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, | |||
| 307 | #endif | 666 | #endif |
| 308 | } | 667 | } |
| 309 | 668 | ||
| 669 | static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, | ||
| 670 | int nents, enum dma_data_direction direction) | ||
| 671 | { | ||
| 672 | BUG(); | ||
| 673 | } | ||
| 674 | |||
| 310 | static int ps3_dma_supported(struct device *_dev, u64 mask) | 675 | static int ps3_dma_supported(struct device *_dev, u64 mask) |
| 311 | { | 676 | { |
| 312 | return mask >= DMA_32BIT_MASK; | 677 | return mask >= DMA_32BIT_MASK; |
| 313 | } | 678 | } |
| 314 | 679 | ||
| 315 | static struct dma_mapping_ops ps3_dma_ops = { | 680 | static struct dma_mapping_ops ps3_sb_dma_ops = { |
| 316 | .alloc_coherent = ps3_alloc_coherent, | 681 | .alloc_coherent = ps3_alloc_coherent, |
| 317 | .free_coherent = ps3_free_coherent, | 682 | .free_coherent = ps3_free_coherent, |
| 318 | .map_single = ps3_map_single, | 683 | .map_single = ps3_sb_map_single, |
| 319 | .unmap_single = ps3_unmap_single, | 684 | .unmap_single = ps3_unmap_single, |
| 320 | .map_sg = ps3_map_sg, | 685 | .map_sg = ps3_sb_map_sg, |
| 321 | .unmap_sg = ps3_unmap_sg, | 686 | .unmap_sg = ps3_sb_unmap_sg, |
| 687 | .dma_supported = ps3_dma_supported | ||
| 688 | }; | ||
| 689 | |||
| 690 | static struct dma_mapping_ops ps3_ioc0_dma_ops = { | ||
| 691 | .alloc_coherent = ps3_alloc_coherent, | ||
| 692 | .free_coherent = ps3_free_coherent, | ||
| 693 | .map_single = ps3_ioc0_map_single, | ||
| 694 | .unmap_single = ps3_unmap_single, | ||
| 695 | .map_sg = ps3_ioc0_map_sg, | ||
| 696 | .unmap_sg = ps3_ioc0_unmap_sg, | ||
| 322 | .dma_supported = ps3_dma_supported | 697 | .dma_supported = ps3_dma_supported |
| 323 | }; | 698 | }; |
| 324 | 699 | ||
| @@ -328,7 +703,7 @@ static struct dma_mapping_ops ps3_dma_ops = { | |||
| 328 | 703 | ||
| 329 | static void ps3_system_bus_release_device(struct device *_dev) | 704 | static void ps3_system_bus_release_device(struct device *_dev) |
| 330 | { | 705 | { |
| 331 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 706 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 332 | kfree(dev); | 707 | kfree(dev); |
| 333 | } | 708 | } |
| 334 | 709 | ||
| @@ -343,19 +718,38 @@ static void ps3_system_bus_release_device(struct device *_dev) | |||
| 343 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) | 718 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) |
| 344 | { | 719 | { |
| 345 | int result; | 720 | int result; |
| 346 | static unsigned int dev_count = 1; | 721 | static unsigned int dev_ioc0_count; |
| 722 | static unsigned int dev_sb_count; | ||
| 723 | static unsigned int dev_vuart_count; | ||
| 347 | 724 | ||
| 348 | dev->core.parent = NULL; | 725 | if (!dev->core.parent) |
| 726 | dev->core.parent = &ps3_system_bus; | ||
| 349 | dev->core.bus = &ps3_system_bus_type; | 727 | dev->core.bus = &ps3_system_bus_type; |
| 350 | dev->core.release = ps3_system_bus_release_device; | 728 | dev->core.release = ps3_system_bus_release_device; |
| 351 | 729 | ||
| 730 | switch (dev->dev_type) { | ||
| 731 | case PS3_DEVICE_TYPE_IOC0: | ||
| 732 | dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops; | ||
| 733 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
| 734 | "ioc0_%02x", ++dev_ioc0_count); | ||
| 735 | break; | ||
| 736 | case PS3_DEVICE_TYPE_SB: | ||
| 737 | dev->core.archdata.dma_ops = &ps3_sb_dma_ops; | ||
| 738 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
| 739 | "sb_%02x", ++dev_sb_count); | ||
| 740 | |||
| 741 | break; | ||
| 742 | case PS3_DEVICE_TYPE_VUART: | ||
| 743 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
| 744 | "vuart_%02x", ++dev_vuart_count); | ||
| 745 | break; | ||
| 746 | default: | ||
| 747 | BUG(); | ||
| 748 | }; | ||
| 749 | |||
| 352 | dev->core.archdata.of_node = NULL; | 750 | dev->core.archdata.of_node = NULL; |
| 353 | dev->core.archdata.dma_ops = &ps3_dma_ops; | ||
| 354 | dev->core.archdata.numa_node = 0; | 751 | dev->core.archdata.numa_node = 0; |
| 355 | 752 | ||
| 356 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x", | ||
| 357 | dev_count++); | ||
| 358 | |||
| 359 | pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); | 753 | pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); |
| 360 | 754 | ||
| 361 | result = device_register(&dev->core); | 755 | result = device_register(&dev->core); |
| @@ -368,9 +762,15 @@ int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) | |||
| 368 | { | 762 | { |
| 369 | int result; | 763 | int result; |
| 370 | 764 | ||
| 765 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
| 766 | |||
| 767 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
| 768 | return -ENODEV; | ||
| 769 | |||
| 371 | drv->core.bus = &ps3_system_bus_type; | 770 | drv->core.bus = &ps3_system_bus_type; |
| 372 | 771 | ||
| 373 | result = driver_register(&drv->core); | 772 | result = driver_register(&drv->core); |
| 773 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
| 374 | return result; | 774 | return result; |
| 375 | } | 775 | } |
| 376 | 776 | ||
| @@ -378,7 +778,9 @@ EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); | |||
| 378 | 778 | ||
| 379 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) | 779 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) |
| 380 | { | 780 | { |
| 781 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
| 381 | driver_unregister(&drv->core); | 782 | driver_unregister(&drv->core); |
| 783 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
| 382 | } | 784 | } |
| 383 | 785 | ||
| 384 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); | 786 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); |
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 1bae8b19b363..802a9ccacb5e 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c | |||
| @@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_time *tm, const char* func, int line) | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) | 41 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) |
| 42 | static void __attribute__ ((unused)) _dump_time(int time, const char* func, | 42 | static void __maybe_unused _dump_time(int time, const char *func, |
| 43 | int line) | 43 | int line) |
| 44 | { | 44 | { |
| 45 | struct rtc_time tm; | 45 | struct rtc_time tm; |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index ae1fc92dc1c9..992ba6753cf2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
| @@ -8,7 +8,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | |||
| 8 | obj-$(CONFIG_SMP) += smp.o | 8 | obj-$(CONFIG_SMP) += smp.o |
| 9 | obj-$(CONFIG_XICS) += xics.o | 9 | obj-$(CONFIG_XICS) += xics.o |
| 10 | obj-$(CONFIG_SCANLOG) += scanlog.o | 10 | obj-$(CONFIG_SCANLOG) += scanlog.o |
| 11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o | 11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o |
| 12 | obj-$(CONFIG_KEXEC) += kexec.o | 12 | obj-$(CONFIG_KEXEC) += kexec.o |
| 13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o | 13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o |
| 14 | obj-$(CONFIG_PCI_MSI) += msi.o | 14 | obj-$(CONFIG_PCI_MSI) += msi.o |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 5f3e6d8659fe..b8770395013d 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * eeh.c | 2 | * eeh.c |
| 3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation | 3 | * Copyright IBM Corporation 2001, 2005, 2006 |
| 4 | * Copyright Dave Engebretsen & Todd Inglett 2001 | ||
| 5 | * Copyright Linas Vepstas 2005, 2006 | ||
| 4 | * | 6 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
| @@ -15,6 +17,8 @@ | |||
| 15 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | * | ||
| 21 | * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
| 18 | */ | 22 | */ |
| 19 | 23 | ||
| 20 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| @@ -117,7 +121,6 @@ static unsigned long no_cfg_addr; | |||
| 117 | static unsigned long ignored_check; | 121 | static unsigned long ignored_check; |
| 118 | static unsigned long total_mmio_ffs; | 122 | static unsigned long total_mmio_ffs; |
| 119 | static unsigned long false_positives; | 123 | static unsigned long false_positives; |
| 120 | static unsigned long ignored_failures; | ||
| 121 | static unsigned long slot_resets; | 124 | static unsigned long slot_resets; |
| 122 | 125 | ||
| 123 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | 126 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) |
| @@ -505,6 +508,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
| 505 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | 508 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", |
| 506 | ret, dn->full_name); | 509 | ret, dn->full_name); |
| 507 | false_positives++; | 510 | false_positives++; |
| 511 | pdn->eeh_false_positives ++; | ||
| 508 | rc = 0; | 512 | rc = 0; |
| 509 | goto dn_unlock; | 513 | goto dn_unlock; |
| 510 | } | 514 | } |
| @@ -513,6 +517,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
| 513 | * they are empty when they don't have children. */ | 517 | * they are empty when they don't have children. */ |
| 514 | if ((rets[0] == 5) && (dn->child == NULL)) { | 518 | if ((rets[0] == 5) && (dn->child == NULL)) { |
| 515 | false_positives++; | 519 | false_positives++; |
| 520 | pdn->eeh_false_positives ++; | ||
| 516 | rc = 0; | 521 | rc = 0; |
| 517 | goto dn_unlock; | 522 | goto dn_unlock; |
| 518 | } | 523 | } |
| @@ -522,6 +527,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
| 522 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | 527 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", |
| 523 | ret, dn->full_name); | 528 | ret, dn->full_name); |
| 524 | false_positives++; | 529 | false_positives++; |
| 530 | pdn->eeh_false_positives ++; | ||
| 525 | rc = 0; | 531 | rc = 0; |
| 526 | goto dn_unlock; | 532 | goto dn_unlock; |
| 527 | } | 533 | } |
| @@ -529,6 +535,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
| 529 | /* If not the kind of error we know about, punt. */ | 535 | /* If not the kind of error we know about, punt. */ |
| 530 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { | 536 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { |
| 531 | false_positives++; | 537 | false_positives++; |
| 538 | pdn->eeh_false_positives ++; | ||
| 532 | rc = 0; | 539 | rc = 0; |
| 533 | goto dn_unlock; | 540 | goto dn_unlock; |
| 534 | } | 541 | } |
| @@ -921,6 +928,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
| 921 | pdn->eeh_mode = 0; | 928 | pdn->eeh_mode = 0; |
| 922 | pdn->eeh_check_count = 0; | 929 | pdn->eeh_check_count = 0; |
| 923 | pdn->eeh_freeze_count = 0; | 930 | pdn->eeh_freeze_count = 0; |
| 931 | pdn->eeh_false_positives = 0; | ||
| 924 | 932 | ||
| 925 | if (status && strcmp(status, "ok") != 0) | 933 | if (status && strcmp(status, "ok") != 0) |
| 926 | return NULL; /* ignore devices with bad status */ | 934 | return NULL; /* ignore devices with bad status */ |
| @@ -1139,7 +1147,8 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
| 1139 | pdn = PCI_DN(dn); | 1147 | pdn = PCI_DN(dn); |
| 1140 | pdn->pcidev = dev; | 1148 | pdn->pcidev = dev; |
| 1141 | 1149 | ||
| 1142 | pci_addr_cache_insert_device (dev); | 1150 | pci_addr_cache_insert_device(dev); |
| 1151 | eeh_sysfs_add_device(dev); | ||
| 1143 | } | 1152 | } |
| 1144 | 1153 | ||
| 1145 | void eeh_add_device_tree_late(struct pci_bus *bus) | 1154 | void eeh_add_device_tree_late(struct pci_bus *bus) |
| @@ -1178,6 +1187,7 @@ static void eeh_remove_device(struct pci_dev *dev) | |||
| 1178 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); | 1187 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
| 1179 | #endif | 1188 | #endif |
| 1180 | pci_addr_cache_remove_device(dev); | 1189 | pci_addr_cache_remove_device(dev); |
| 1190 | eeh_sysfs_remove_device(dev); | ||
| 1181 | 1191 | ||
| 1182 | dn = pci_device_to_OF_node(dev); | 1192 | dn = pci_device_to_OF_node(dev); |
| 1183 | if (PCI_DN(dn)->pcidev) { | 1193 | if (PCI_DN(dn)->pcidev) { |
| @@ -1214,11 +1224,10 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
| 1214 | "check not wanted=%ld\n" | 1224 | "check not wanted=%ld\n" |
| 1215 | "eeh_total_mmio_ffs=%ld\n" | 1225 | "eeh_total_mmio_ffs=%ld\n" |
| 1216 | "eeh_false_positives=%ld\n" | 1226 | "eeh_false_positives=%ld\n" |
| 1217 | "eeh_ignored_failures=%ld\n" | ||
| 1218 | "eeh_slot_resets=%ld\n", | 1227 | "eeh_slot_resets=%ld\n", |
| 1219 | no_device, no_dn, no_cfg_addr, | 1228 | no_device, no_dn, no_cfg_addr, |
| 1220 | ignored_check, total_mmio_ffs, | 1229 | ignored_check, total_mmio_ffs, |
| 1221 | false_positives, ignored_failures, | 1230 | false_positives, |
| 1222 | slot_resets); | 1231 | slot_resets); |
| 1223 | } | 1232 | } |
| 1224 | 1233 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index f2bae04424f8..e49c815eae23 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | * eeh_cache.c | 2 | * eeh_cache.c |
| 3 | * PCI address cache; allows the lookup of PCI devices based on I/O address | 3 | * PCI address cache; allows the lookup of PCI devices based on I/O address |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation | 5 | * Copyright IBM Corporation 2004 |
| 6 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2004 | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -295,6 +296,8 @@ void __init pci_addr_cache_build(void) | |||
| 295 | continue; | 296 | continue; |
| 296 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ | 297 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ |
| 297 | PCI_DN(dn)->pcidev = dev; | 298 | PCI_DN(dn)->pcidev = dev; |
| 299 | |||
| 300 | eeh_sysfs_add_device(dev); | ||
| 298 | } | 301 | } |
| 299 | 302 | ||
| 300 | #ifdef DEBUG | 303 | #ifdef DEBUG |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 161a5844ab6c..15e015ef6865 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. | 2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. |
| 3 | * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org> | 3 | * Copyright IBM Corp. 2004 2005 |
| 4 | * Copyright Linas Vepstas <linas@linas.org> 2004, 2005 | ||
| 4 | * | 5 | * |
| 5 | * All rights reserved. | 6 | * All rights reserved. |
| 6 | * | 7 | * |
| @@ -19,8 +20,7 @@ | |||
| 19 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 21 | * | 22 | * |
| 22 | * Send feedback to <linas@us.ibm.com> | 23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> |
| 23 | * | ||
| 24 | */ | 24 | */ |
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c new file mode 100644 index 000000000000..15e13b568904 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* | ||
| 2 | * Sysfs entries for PCI Error Recovery for PAPR-compliant platform. | ||
| 3 | * Copyright IBM Corporation 2007 | ||
| 4 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2007 | ||
| 5 | * | ||
| 6 | * All rights reserved. | ||
| 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 (at | ||
| 11 | * your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 16 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
| 17 | * details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 22 | * | ||
| 23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
| 24 | */ | ||
| 25 | #include <linux/pci.h> | ||
| 26 | #include <asm/ppc-pci.h> | ||
| 27 | #include <asm/pci-bridge.h> | ||
| 28 | #include <linux/kobject.h> | ||
| 29 | |||
| 30 | /** | ||
| 31 | * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic | ||
| 32 | * @_name: name of file in sysfs directory | ||
| 33 | * @_memb: name of member in struct pci_dn to access | ||
| 34 | * @_format: printf format for display | ||
| 35 | * | ||
| 36 | * All of the attributes look very similar, so just | ||
| 37 | * auto-gen a cut-n-paste routine to display them. | ||
| 38 | */ | ||
| 39 | #define EEH_SHOW_ATTR(_name,_memb,_format) \ | ||
| 40 | static ssize_t eeh_show_##_name(struct device *dev, \ | ||
| 41 | struct device_attribute *attr, char *buf) \ | ||
| 42 | { \ | ||
| 43 | struct pci_dev *pdev = to_pci_dev(dev); \ | ||
| 44 | struct device_node *dn = pci_device_to_OF_node(pdev); \ | ||
| 45 | struct pci_dn *pdn; \ | ||
| 46 | \ | ||
| 47 | if (!dn || PCI_DN(dn) == NULL) \ | ||
| 48 | return 0; \ | ||
| 49 | \ | ||
| 50 | pdn = PCI_DN(dn); \ | ||
| 51 | return sprintf(buf, _format "\n", pdn->_memb); \ | ||
| 52 | } \ | ||
| 53 | static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL); | ||
| 54 | |||
| 55 | |||
| 56 | EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x"); | ||
| 57 | EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x"); | ||
| 58 | EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x"); | ||
| 59 | EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d"); | ||
| 60 | EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d"); | ||
| 61 | EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d"); | ||
| 62 | |||
| 63 | void eeh_sysfs_add_device(struct pci_dev *pdev) | ||
| 64 | { | ||
| 65 | int rc=0; | ||
| 66 | |||
| 67 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); | ||
| 68 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
| 69 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
| 70 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
| 71 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
| 72 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
| 73 | |||
| 74 | if (rc) | ||
| 75 | printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); | ||
| 76 | } | ||
| 77 | |||
| 78 | void eeh_sysfs_remove_device(struct pci_dev *pdev) | ||
| 79 | { | ||
| 80 | device_remove_file(&pdev->dev, &dev_attr_eeh_mode); | ||
| 81 | device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
| 82 | device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
| 83 | device_remove_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
| 84 | device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
| 85 | device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
| 86 | } | ||
| 87 | |||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 362dfbc260a6..8cc6eeeaae2f 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -373,12 +373,23 @@ static void pSeries_lpar_hptab_clear(void) | |||
| 373 | { | 373 | { |
| 374 | unsigned long size_bytes = 1UL << ppc64_pft_size; | 374 | unsigned long size_bytes = 1UL << ppc64_pft_size; |
| 375 | unsigned long hpte_count = size_bytes >> 4; | 375 | unsigned long hpte_count = size_bytes >> 4; |
| 376 | unsigned long dummy1, dummy2; | 376 | unsigned long dummy1, dummy2, dword0; |
| 377 | long lpar_rc; | ||
| 377 | int i; | 378 | int i; |
| 378 | 379 | ||
| 379 | /* TODO: Use bulk call */ | 380 | /* TODO: Use bulk call */ |
| 380 | for (i = 0; i < hpte_count; i++) | 381 | for (i = 0; i < hpte_count; i++) { |
| 381 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | 382 | /* dont remove HPTEs with VRMA mappings */ |
| 383 | lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, | ||
| 384 | &dummy1, &dummy2); | ||
| 385 | if (lpar_rc == H_NOT_FOUND) { | ||
| 386 | lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); | ||
| 387 | if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) | ||
| 388 | != HPTE_V_VRMA_MASK)) | ||
| 389 | /* Can be hpte for 1TB Seg. So remove it */ | ||
| 390 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | ||
| 391 | } | ||
| 392 | } | ||
| 382 | } | 393 | } |
| 383 | 394 | ||
| 384 | /* | 395 | /* |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index ffaf6c5c517b..47f0e0857f0e 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
| @@ -110,8 +110,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | |||
| 114 | eeh_add_device_tree_late(bus); | ||
| 115 | } | 113 | } |
| 116 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); | 114 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); |
| 117 | 115 | ||
| @@ -139,6 +137,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev) | |||
| 139 | 137 | ||
| 140 | /* Make the discovered devices available */ | 138 | /* Make the discovered devices available */ |
| 141 | pci_bus_add_devices(child_bus); | 139 | pci_bus_add_devices(child_bus); |
| 140 | |||
| 141 | eeh_add_device_tree_late(child_bus); | ||
| 142 | return 0; | 142 | return 0; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| @@ -171,6 +171,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
| 171 | if (!list_empty(&bus->devices)) { | 171 | if (!list_empty(&bus->devices)) { |
| 172 | pcibios_fixup_new_pci_devices(bus, 0); | 172 | pcibios_fixup_new_pci_devices(bus, 0); |
| 173 | pci_bus_add_devices(bus); | 173 | pci_bus_add_devices(bus); |
| 174 | eeh_add_device_tree_late(bus); | ||
| 174 | } | 175 | } |
| 175 | } else if (mode == PCI_PROBE_NORMAL) { | 176 | } else if (mode == PCI_PROBE_NORMAL) { |
| 176 | /* use legacy probe */ | 177 | /* use legacy probe */ |
| @@ -179,6 +180,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
| 179 | if (num) { | 180 | if (num) { |
| 180 | pcibios_fixup_new_pci_devices(bus, 1); | 181 | pcibios_fixup_new_pci_devices(bus, 1); |
| 181 | pci_bus_add_devices(bus); | 182 | pci_bus_add_devices(bus); |
| 183 | eeh_add_device_tree_late(bus); | ||
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | list_for_each_entry(dev, &bus->devices, bus_list) | 186 | list_for_each_entry(dev, &bus->devices, bus_list) |
| @@ -200,8 +202,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
| 200 | rtas_setup_phb(phb); | 202 | rtas_setup_phb(phb); |
| 201 | pci_process_bridge_OF_ranges(phb, dn, 0); | 203 | pci_process_bridge_OF_ranges(phb, dn, 0); |
| 202 | 204 | ||
| 203 | pci_setup_phb_io_dynamic(phb, primary); | ||
| 204 | |||
| 205 | pci_devs_phb_init_dynamic(phb); | 205 | pci_devs_phb_init_dynamic(phb); |
| 206 | 206 | ||
| 207 | if (dn->child) | 207 | if (dn->child) |
| @@ -210,6 +210,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
| 210 | scan_phb(phb); | 210 | scan_phb(phb); |
| 211 | pcibios_fixup_new_pci_devices(phb->bus, 0); | 211 | pcibios_fixup_new_pci_devices(phb->bus, 0); |
| 212 | pci_bus_add_devices(phb->bus); | 212 | pci_bus_add_devices(phb->bus); |
| 213 | eeh_add_device_tree_late(phb->bus); | ||
| 213 | 214 | ||
| 214 | return phb; | 215 | return phb; |
| 215 | } | 216 | } |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 2e4d10c9eea8..d003c80fa31d 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
| @@ -108,6 +108,21 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, | |||
| 108 | return rc; | 108 | return rc; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */ | ||
| 112 | static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex, | ||
| 113 | unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) | ||
| 114 | { | ||
| 115 | long rc; | ||
| 116 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
| 117 | |||
| 118 | rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex); | ||
| 119 | |||
| 120 | *old_pteh_ret = retbuf[0]; | ||
| 121 | *old_ptel_ret = retbuf[1]; | ||
| 122 | |||
| 123 | return rc; | ||
| 124 | } | ||
| 125 | |||
| 111 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, | 126 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, |
| 112 | unsigned long avpn) | 127 | unsigned long avpn) |
| 113 | { | 128 | { |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 2729d559fd91..61e19f78b923 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
| @@ -33,6 +33,8 @@ static inline void setup_kexec_cpu_down_xics(void) { } | |||
| 33 | static inline void setup_kexec_cpu_down_mpic(void) { } | 33 | static inline void setup_kexec_cpu_down_mpic(void) { } |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | extern void pSeries_final_fixup(void); | ||
| 37 | |||
| 36 | /* Poweron flag used for enabling auto ups restart */ | 38 | /* Poweron flag used for enabling auto ups restart */ |
| 37 | extern unsigned long rtas_poweron_auto; | 39 | extern unsigned long rtas_poweron_auto; |
| 38 | 40 | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 5aa97aff3391..c02f8742c54d 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
| @@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist | |||
| 123 | strcpy(np->full_name, path); | 123 | strcpy(np->full_name, path); |
| 124 | 124 | ||
| 125 | np->properties = proplist; | 125 | np->properties = proplist; |
| 126 | OF_MARK_DYNAMIC(np); | 126 | of_node_set_flag(np, OF_DYNAMIC); |
| 127 | kref_init(&np->kref); | 127 | kref_init(&np->kref); |
| 128 | 128 | ||
| 129 | np->parent = derive_parent(path); | 129 | np->parent = derive_parent(path); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 470db6efaeb6..de6c2efd0479 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -399,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
| 399 | * a good time to find other work to dispatch. | 399 | * a good time to find other work to dispatch. |
| 400 | */ | 400 | */ |
| 401 | get_lppaca()->idle = 1; | 401 | get_lppaca()->idle = 1; |
| 402 | get_lppaca()->donate_dedicated_cpu = 1; | ||
| 402 | 403 | ||
| 403 | /* | 404 | /* |
| 404 | * We come in with interrupts disabled, and need_resched() | 405 | * We come in with interrupts disabled, and need_resched() |
| @@ -431,6 +432,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
| 431 | 432 | ||
| 432 | out: | 433 | out: |
| 433 | HMT_medium(); | 434 | HMT_medium(); |
| 435 | get_lppaca()->donate_dedicated_cpu = 0; | ||
| 434 | get_lppaca()->idle = 0; | 436 | get_lppaca()->idle = 0; |
| 435 | } | 437 | } |
| 436 | 438 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index f1df942072bb..5bd90a7eb763 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
| @@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
| 156 | 156 | ||
| 157 | 157 | ||
| 158 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
| 159 | static int get_irq_server(unsigned int virq) | 159 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
| 160 | { | 160 | { |
| 161 | unsigned int server; | 161 | int server; |
| 162 | /* For the moment only implement delivery to all cpus or one cpu */ | 162 | /* For the moment only implement delivery to all cpus or one cpu */ |
| 163 | cpumask_t cpumask = irq_desc[virq].affinity; | 163 | cpumask_t cpumask = irq_desc[virq].affinity; |
| 164 | cpumask_t tmp = CPU_MASK_NONE; | 164 | cpumask_t tmp = CPU_MASK_NONE; |
| @@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq) | |||
| 166 | if (!distribute_irqs) | 166 | if (!distribute_irqs) |
| 167 | return default_server; | 167 | return default_server; |
| 168 | 168 | ||
| 169 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 169 | if (!cpus_equal(cpumask, CPU_MASK_ALL)) { |
| 170 | server = default_distrib_server; | ||
| 171 | } else { | ||
| 172 | cpus_and(tmp, cpu_online_map, cpumask); | 170 | cpus_and(tmp, cpu_online_map, cpumask); |
| 173 | 171 | ||
| 174 | if (cpus_empty(tmp)) | 172 | server = first_cpu(tmp); |
| 175 | server = default_distrib_server; | 173 | |
| 176 | else | 174 | if (server < NR_CPUS) |
| 177 | server = get_hard_smp_processor_id(first_cpu(tmp)); | 175 | return get_hard_smp_processor_id(server); |
| 176 | |||
| 177 | if (strict_check) | ||
| 178 | return -1; | ||
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | return server; | 181 | if (cpus_equal(cpu_online_map, cpu_present_map)) |
| 182 | return default_distrib_server; | ||
| 181 | 183 | ||
| 184 | return default_server; | ||
| 182 | } | 185 | } |
| 183 | #else | 186 | #else |
| 184 | static int get_irq_server(unsigned int virq) | 187 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
| 185 | { | 188 | { |
| 186 | return default_server; | 189 | return default_server; |
| 187 | } | 190 | } |
| @@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
| 192 | { | 195 | { |
| 193 | unsigned int irq; | 196 | unsigned int irq; |
| 194 | int call_status; | 197 | int call_status; |
| 195 | unsigned int server; | 198 | int server; |
| 196 | 199 | ||
| 197 | pr_debug("xics: unmask virq %d\n", virq); | 200 | pr_debug("xics: unmask virq %d\n", virq); |
| 198 | 201 | ||
| @@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
| 201 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 204 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
| 202 | return; | 205 | return; |
| 203 | 206 | ||
| 204 | server = get_irq_server(virq); | 207 | server = get_irq_server(virq, 0); |
| 205 | 208 | ||
| 206 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 209 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
| 207 | DEFAULT_PRIORITY); | 210 | DEFAULT_PRIORITY); |
| @@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
| 398 | unsigned int irq; | 401 | unsigned int irq; |
| 399 | int status; | 402 | int status; |
| 400 | int xics_status[2]; | 403 | int xics_status[2]; |
| 401 | unsigned long newmask; | 404 | int irq_server; |
| 402 | cpumask_t tmp = CPU_MASK_NONE; | ||
| 403 | 405 | ||
| 404 | irq = (unsigned int)irq_map[virq].hwirq; | 406 | irq = (unsigned int)irq_map[virq].hwirq; |
| 405 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 407 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
| @@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
| 413 | return; | 415 | return; |
| 414 | } | 416 | } |
| 415 | 417 | ||
| 416 | /* For the moment only implement delivery to all cpus or one cpu */ | 418 | /* |
| 417 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 419 | * For the moment only implement delivery to all cpus or one cpu. |
| 418 | newmask = default_distrib_server; | 420 | * Get current irq_server for the given irq |
| 419 | } else { | 421 | */ |
| 420 | cpus_and(tmp, cpu_online_map, cpumask); | 422 | irq_server = get_irq_server(irq, 1); |
| 421 | if (cpus_empty(tmp)) | 423 | if (irq_server == -1) { |
| 422 | return; | 424 | char cpulist[128]; |
| 423 | newmask = get_hard_smp_processor_id(first_cpu(tmp)); | 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
| 426 | printk(KERN_WARNING "xics_set_affinity: No online cpus in " | ||
| 427 | "the mask %s for irq %d\n", cpulist, virq); | ||
| 428 | return; | ||
| 424 | } | 429 | } |
| 425 | 430 | ||
| 426 | status = rtas_call(ibm_set_xive, 3, 1, NULL, | 431 | status = rtas_call(ibm_set_xive, 3, 1, NULL, |
| 427 | irq, newmask, xics_status[1]); | 432 | irq, irq_server, xics_status[1]); |
| 428 | 433 | ||
| 429 | if (status) { | 434 | if (status) { |
| 430 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " | 435 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index c3ce0bd12c0b..f65078c3d3b3 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
| @@ -5,7 +5,6 @@ endif | |||
| 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o |
| 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
| 7 | 7 | ||
| 8 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
| 9 | obj-$(CONFIG_PPC_MPC106) += grackle.o | 8 | obj-$(CONFIG_PPC_MPC106) += grackle.o |
| 10 | obj-$(CONFIG_PPC_DCR) += dcr.o | 9 | obj-$(CONFIG_PPC_DCR) += dcr.o |
| 11 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o | 10 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o |
| @@ -13,16 +12,19 @@ obj-$(CONFIG_PPC_PMI) += pmi.o | |||
| 13 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 12 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
| 14 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 13 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
| 15 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 14 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
| 16 | obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o | ||
| 17 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 15 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
| 18 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ | 16 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ |
| 19 | mv64x60-$(CONFIG_PCI) += mv64x60_pci.o | 17 | mv64x60-$(CONFIG_PCI) += mv64x60_pci.o |
| 20 | obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o | 18 | obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o |
| 19 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o | ||
| 21 | 20 | ||
| 22 | # contains only the suspend handler for time | 21 | # contains only the suspend handler for time |
| 22 | ifeq ($(CONFIG_RTC_CLASS),) | ||
| 23 | obj-$(CONFIG_PM) += timer.o | 23 | obj-$(CONFIG_PM) += timer.o |
| 24 | endif | ||
| 24 | 25 | ||
| 25 | ifeq ($(CONFIG_PPC_MERGE),y) | 26 | ifeq ($(CONFIG_PPC_MERGE),y) |
| 27 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
| 26 | obj-$(CONFIG_PPC_I8259) += i8259.o | 28 | obj-$(CONFIG_PPC_I8259) += i8259.o |
| 27 | obj-$(CONFIG_PPC_83xx) += ipic.o | 29 | obj-$(CONFIG_PPC_83xx) += ipic.o |
| 28 | obj-$(CONFIG_4xx) += uic.o | 30 | obj-$(CONFIG_4xx) += uic.o |
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c deleted file mode 100644 index 041c07e8b665..000000000000 --- a/arch/powerpc/sysdev/fsl_pcie.c +++ /dev/null | |||
| @@ -1,171 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support for indirect PCI bridges. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998 Gabriel Paubert. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * "Temporary" MPC8548 Errata file - | ||
| 12 | * The standard indirect_pci code should work with future silicon versions. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/bootmem.h> | ||
| 21 | |||
| 22 | #include <asm/io.h> | ||
| 23 | #include <asm/prom.h> | ||
| 24 | #include <asm/pci-bridge.h> | ||
| 25 | #include <asm/machdep.h> | ||
| 26 | |||
| 27 | #define PCI_CFG_OUT out_be32 | ||
| 28 | |||
| 29 | /* ERRATA PCI-Ex 14 PCIE Controller timeout */ | ||
| 30 | #define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) | ||
| 31 | |||
| 32 | |||
| 33 | static int | ||
| 34 | indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 35 | int len, u32 *val) | ||
| 36 | { | ||
| 37 | struct pci_controller *hose = bus->sysdata; | ||
| 38 | volatile void __iomem *cfg_data; | ||
| 39 | u32 temp; | ||
| 40 | |||
| 41 | if (ppc_md.pci_exclude_device) | ||
| 42 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
| 43 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 44 | |||
| 45 | /* Possible artifact of CDCpp50937 needs further investigation */ | ||
| 46 | if (devfn != 0x0 && bus->number == 0xff) | ||
| 47 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 48 | |||
| 49 | PCIE_FIX; | ||
| 50 | if (bus->number == 0xff) { | ||
| 51 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 52 | (0x80000000 | ((offset & 0xf00) << 16) | | ||
| 53 | ((bus->number - hose->bus_offset) << 16) | ||
| 54 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
| 55 | } else { | ||
| 56 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 57 | (0x80000001 | ((offset & 0xf00) << 16) | | ||
| 58 | ((bus->number - hose->bus_offset) << 16) | ||
| 59 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Note: the caller has already checked that offset is | ||
| 64 | * suitably aligned and that len is 1, 2 or 4. | ||
| 65 | */ | ||
| 66 | /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ | ||
| 67 | cfg_data = hose->cfg_data; | ||
| 68 | PCIE_FIX; | ||
| 69 | temp = in_le32(cfg_data); | ||
| 70 | switch (len) { | ||
| 71 | case 1: | ||
| 72 | *val = (temp >> (((offset & 3))*8)) & 0xff; | ||
| 73 | break; | ||
| 74 | case 2: | ||
| 75 | *val = (temp >> (((offset & 3))*8)) & 0xffff; | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | *val = temp; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | return PCIBIOS_SUCCESSFUL; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int | ||
| 85 | indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 86 | int len, u32 val) | ||
| 87 | { | ||
| 88 | struct pci_controller *hose = bus->sysdata; | ||
| 89 | volatile void __iomem *cfg_data; | ||
| 90 | u32 temp; | ||
| 91 | |||
| 92 | if (ppc_md.pci_exclude_device) | ||
| 93 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
| 94 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 95 | |||
| 96 | /* Possible artifact of CDCpp50937 needs further investigation */ | ||
| 97 | if (devfn != 0x0 && bus->number == 0xff) | ||
| 98 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 99 | |||
| 100 | PCIE_FIX; | ||
| 101 | if (bus->number == 0xff) { | ||
| 102 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 103 | (0x80000000 | ((offset & 0xf00) << 16) | | ||
| 104 | ((bus->number - hose->bus_offset) << 16) | ||
| 105 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
| 106 | } else { | ||
| 107 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 108 | (0x80000001 | ((offset & 0xf00) << 16) | | ||
| 109 | ((bus->number - hose->bus_offset) << 16) | ||
| 110 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
| 111 | } | ||
| 112 | |||
| 113 | /* | ||
| 114 | * Note: the caller has already checked that offset is | ||
| 115 | * suitably aligned and that len is 1, 2 or 4. | ||
| 116 | */ | ||
| 117 | /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ | ||
| 118 | cfg_data = hose->cfg_data; | ||
| 119 | switch (len) { | ||
| 120 | case 1: | ||
| 121 | PCIE_FIX; | ||
| 122 | temp = in_le32(cfg_data); | ||
| 123 | temp = (temp & ~(0xff << ((offset & 3) * 8))) | | ||
| 124 | (val << ((offset & 3) * 8)); | ||
| 125 | PCIE_FIX; | ||
| 126 | out_le32(cfg_data, temp); | ||
| 127 | break; | ||
| 128 | case 2: | ||
| 129 | PCIE_FIX; | ||
| 130 | temp = in_le32(cfg_data); | ||
| 131 | temp = (temp & ~(0xffff << ((offset & 3) * 8))); | ||
| 132 | temp |= (val << ((offset & 3) * 8)) ; | ||
| 133 | PCIE_FIX; | ||
| 134 | out_le32(cfg_data, temp); | ||
| 135 | break; | ||
| 136 | default: | ||
| 137 | PCIE_FIX; | ||
| 138 | out_le32(cfg_data, val); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | PCIE_FIX; | ||
| 142 | return PCIBIOS_SUCCESSFUL; | ||
| 143 | } | ||
| 144 | |||
| 145 | static struct pci_ops indirect_pcie_ops = { | ||
| 146 | indirect_read_config_pcie, | ||
| 147 | indirect_write_config_pcie | ||
| 148 | }; | ||
| 149 | |||
| 150 | void __init | ||
| 151 | setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, | ||
| 152 | void __iomem * cfg_data) | ||
| 153 | { | ||
| 154 | hose->cfg_addr = cfg_addr; | ||
| 155 | hose->cfg_data = cfg_data; | ||
| 156 | hose->ops = &indirect_pcie_ops; | ||
| 157 | } | ||
| 158 | |||
| 159 | void __init | ||
| 160 | setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) | ||
| 161 | { | ||
| 162 | unsigned long base = cfg_addr & PAGE_MASK; | ||
| 163 | void __iomem *mbase, *addr, *data; | ||
| 164 | |||
| 165 | mbase = ioremap(base, PAGE_SIZE); | ||
| 166 | addr = mbase + (cfg_addr & ~PAGE_MASK); | ||
| 167 | if ((cfg_data & PAGE_MASK) != base) | ||
| 168 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); | ||
| 169 | data = mbase + (cfg_data & ~PAGE_MASK); | ||
| 170 | setup_indirect_pcie_nomap(hose, addr, data); | ||
| 171 | } | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index cad175724359..c0ddc80d8160 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
| @@ -1028,6 +1028,19 @@ err: | |||
| 1028 | 1028 | ||
| 1029 | arch_initcall(fs_enet_of_init); | 1029 | arch_initcall(fs_enet_of_init); |
| 1030 | 1030 | ||
| 1031 | static int __init fsl_pcmcia_of_init(void) | ||
| 1032 | { | ||
| 1033 | struct device_node *np = NULL; | ||
| 1034 | /* | ||
| 1035 | * Register all the devices which type is "pcmcia" | ||
| 1036 | */ | ||
| 1037 | while ((np = of_find_compatible_node(np, | ||
| 1038 | "pcmcia", "fsl,pq-pcmcia")) != NULL) | ||
| 1039 | of_platform_device_create(np, "m8xx-pcmcia", NULL); | ||
| 1040 | return 0; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | arch_initcall(fsl_pcmcia_of_init); | ||
| 1031 | 1044 | ||
| 1032 | static const char *smc_regs = "regs"; | 1045 | static const char *smc_regs = "regs"; |
| 1033 | static const char *smc_pram = "pram"; | 1046 | static const char *smc_pram = "pram"; |
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index e71488469704..c7e6e859b393 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c | |||
| @@ -33,18 +33,27 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 33 | struct pci_controller *hose = bus->sysdata; | 33 | struct pci_controller *hose = bus->sysdata; |
| 34 | volatile void __iomem *cfg_data; | 34 | volatile void __iomem *cfg_data; |
| 35 | u8 cfg_type = 0; | 35 | u8 cfg_type = 0; |
| 36 | u32 bus_no, reg; | ||
| 36 | 37 | ||
| 37 | if (ppc_md.pci_exclude_device) | 38 | if (ppc_md.pci_exclude_device) |
| 38 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 39 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
| 39 | return PCIBIOS_DEVICE_NOT_FOUND; | 40 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 40 | 41 | ||
| 41 | if (hose->set_cfg_type) | 42 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) |
| 42 | if (bus->number != hose->first_busno) | 43 | if (bus->number != hose->first_busno) |
| 43 | cfg_type = 1; | 44 | cfg_type = 1; |
| 44 | 45 | ||
| 45 | PCI_CFG_OUT(hose->cfg_addr, | 46 | bus_no = (bus->number == hose->first_busno) ? |
| 46 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | 47 | hose->self_busno : bus->number; |
| 47 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | 48 | |
| 49 | if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) | ||
| 50 | reg = ((offset & 0xf00) << 16) | (offset & 0xfc); | ||
| 51 | else | ||
| 52 | reg = offset & 0xfc; | ||
| 53 | |||
| 54 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 55 | (0x80000000 | (bus_no << 16) | ||
| 56 | | (devfn << 8) | reg | cfg_type)); | ||
| 48 | 57 | ||
| 49 | /* | 58 | /* |
| 50 | * Note: the caller has already checked that offset is | 59 | * Note: the caller has already checked that offset is |
| @@ -72,18 +81,33 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 72 | struct pci_controller *hose = bus->sysdata; | 81 | struct pci_controller *hose = bus->sysdata; |
| 73 | volatile void __iomem *cfg_data; | 82 | volatile void __iomem *cfg_data; |
| 74 | u8 cfg_type = 0; | 83 | u8 cfg_type = 0; |
| 84 | u32 bus_no, reg; | ||
| 75 | 85 | ||
| 76 | if (ppc_md.pci_exclude_device) | 86 | if (ppc_md.pci_exclude_device) |
| 77 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 87 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
| 78 | return PCIBIOS_DEVICE_NOT_FOUND; | 88 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 79 | 89 | ||
| 80 | if (hose->set_cfg_type) | 90 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) |
| 81 | if (bus->number != hose->first_busno) | 91 | if (bus->number != hose->first_busno) |
| 82 | cfg_type = 1; | 92 | cfg_type = 1; |
| 83 | 93 | ||
| 84 | PCI_CFG_OUT(hose->cfg_addr, | 94 | bus_no = (bus->number == hose->first_busno) ? |
| 85 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | 95 | hose->self_busno : bus->number; |
| 86 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | 96 | |
| 97 | if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) | ||
| 98 | reg = ((offset & 0xf00) << 16) | (offset & 0xfc); | ||
| 99 | else | ||
| 100 | reg = offset & 0xfc; | ||
| 101 | |||
| 102 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 103 | (0x80000000 | (bus_no << 16) | ||
| 104 | | (devfn << 8) | reg | cfg_type)); | ||
| 105 | |||
| 106 | /* surpress setting of PCI_PRIMARY_BUS */ | ||
| 107 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) | ||
| 108 | if ((offset == PCI_PRIMARY_BUS) && | ||
| 109 | (bus->number == hose->first_busno)) | ||
| 110 | val &= 0xffffff00; | ||
| 87 | 111 | ||
| 88 | /* | 112 | /* |
| 89 | * Note: the caller has already checked that offset is | 113 | * Note: the caller has already checked that offset is |
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h index afa2ee6717c1..9fe00eebdc8b 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.h +++ b/arch/powerpc/sysdev/mpc8xx_pic.h | |||
| @@ -4,9 +4,16 @@ | |||
| 4 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
| 5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
| 6 | 6 | ||
| 7 | extern struct hw_interrupt_type mpc8xx_pic; | ||
| 8 | |||
| 9 | int mpc8xx_pic_init(void); | 7 | int mpc8xx_pic_init(void); |
| 10 | unsigned int mpc8xx_get_irq(void); | 8 | unsigned int mpc8xx_get_irq(void); |
| 11 | 9 | ||
| 10 | /* | ||
| 11 | * Some internal interrupt registers use an 8-bit mask for the interrupt | ||
| 12 | * level instead of a number. | ||
| 13 | */ | ||
| 14 | static inline uint mk_int_int_mask(uint mask) | ||
| 15 | { | ||
| 16 | return (1 << (7 - (mask/2))); | ||
| 17 | } | ||
| 18 | |||
| 12 | #endif /* _PPC_KERNEL_PPC8xx_H */ | 19 | #endif /* _PPC_KERNEL_PPC8xx_H */ |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 4b0a9c88eeb3..b618fa60aef3 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/stddef.h> | 12 | #include <linux/stddef.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/console.h> | ||
| 15 | #include <linux/mv643xx.h> | 16 | #include <linux/mv643xx.h> |
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | 18 | ||
| @@ -420,3 +421,30 @@ error: | |||
| 420 | return err; | 421 | return err; |
| 421 | } | 422 | } |
| 422 | arch_initcall(mv64x60_device_setup); | 423 | arch_initcall(mv64x60_device_setup); |
| 424 | |||
| 425 | static int __init mv64x60_add_mpsc_console(void) | ||
| 426 | { | ||
| 427 | struct device_node *np = NULL; | ||
| 428 | const char *prop; | ||
| 429 | |||
| 430 | prop = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
| 431 | if (prop == NULL) | ||
| 432 | goto not_mpsc; | ||
| 433 | |||
| 434 | np = of_find_node_by_path(prop); | ||
| 435 | if (!np) | ||
| 436 | goto not_mpsc; | ||
| 437 | |||
| 438 | if (!of_device_is_compatible(np, "marvell,mpsc")) | ||
| 439 | goto not_mpsc; | ||
| 440 | |||
| 441 | prop = of_get_property(np, "block-index", NULL); | ||
| 442 | if (!prop) | ||
| 443 | goto not_mpsc; | ||
| 444 | |||
| 445 | add_preferred_console("ttyMM", *(int *)prop, NULL); | ||
| 446 | |||
| 447 | not_mpsc: | ||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | console_initcall(mv64x60_add_mpsc_console); | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index b5aef4cbc8d2..45db86c2363c 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c | |||
| @@ -137,18 +137,15 @@ static int __init mv64x60_add_bridge(struct device_node *dev) | |||
| 137 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 137 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
| 138 | " bus 0\n", dev->full_name); | 138 | " bus 0\n", dev->full_name); |
| 139 | 139 | ||
| 140 | hose = pcibios_alloc_controller(); | 140 | hose = pcibios_alloc_controller(dev); |
| 141 | if (!hose) | 141 | if (!hose) |
| 142 | return -ENOMEM; | 142 | return -ENOMEM; |
| 143 | 143 | ||
| 144 | hose->arch_data = dev; | ||
| 145 | hose->set_cfg_type = 1; | ||
| 146 | |||
| 147 | hose->first_busno = bus_range ? bus_range[0] : 0; | 144 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 148 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 145 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
| 149 | 146 | ||
| 150 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); | 147 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); |
| 151 | hose->bus_offset = hose->first_busno; | 148 | hose->self_busno = hose->first_busno; |
| 152 | 149 | ||
| 153 | printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " | 150 | printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " |
| 154 | "Firmware bus number: %d->%d\n", | 151 | "Firmware bus number: %d->%d\n", |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c index ac12a44d516f..f970e5415ac0 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc.c +++ b/arch/powerpc/sysdev/qe_lib/ucc.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
| 21 | #include <linux/module.h> | ||
| 21 | 22 | ||
| 22 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
| 23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| @@ -40,6 +41,7 @@ int ucc_set_qe_mux_mii_mng(int ucc_num) | |||
| 40 | 41 | ||
| 41 | return 0; | 42 | return 0; |
| 42 | } | 43 | } |
| 44 | EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng); | ||
| 43 | 45 | ||
| 44 | int ucc_set_type(int ucc_num, struct ucc_common *regs, | 46 | int ucc_set_type(int ucc_num, struct ucc_common *regs, |
| 45 | enum ucc_speed_type speed) | 47 | enum ucc_speed_type speed) |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 9143236853fc..3df202e8d332 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 22 | #include <linux/module.h> | ||
| 22 | 23 | ||
| 23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 24 | #include <asm/immap_qe.h> | 25 | #include <asm/immap_qe.h> |
| @@ -70,6 +71,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf) | |||
| 70 | printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", | 71 | printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", |
| 71 | (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); | 72 | (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); |
| 72 | } | 73 | } |
| 74 | EXPORT_SYMBOL(ucc_fast_dump_regs); | ||
| 73 | 75 | ||
| 74 | u32 ucc_fast_get_qe_cr_subblock(int uccf_num) | 76 | u32 ucc_fast_get_qe_cr_subblock(int uccf_num) |
| 75 | { | 77 | { |
| @@ -85,11 +87,13 @@ u32 ucc_fast_get_qe_cr_subblock(int uccf_num) | |||
| 85 | default: return QE_CR_SUBBLOCK_INVALID; | 87 | default: return QE_CR_SUBBLOCK_INVALID; |
| 86 | } | 88 | } |
| 87 | } | 89 | } |
| 90 | EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock); | ||
| 88 | 91 | ||
| 89 | void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) | 92 | void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) |
| 90 | { | 93 | { |
| 91 | out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD); | 94 | out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD); |
| 92 | } | 95 | } |
| 96 | EXPORT_SYMBOL(ucc_fast_transmit_on_demand); | ||
| 93 | 97 | ||
| 94 | void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) | 98 | void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) |
| 95 | { | 99 | { |
| @@ -110,6 +114,7 @@ void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) | |||
| 110 | } | 114 | } |
| 111 | out_be32(&uf_regs->gumr, gumr); | 115 | out_be32(&uf_regs->gumr, gumr); |
| 112 | } | 116 | } |
| 117 | EXPORT_SYMBOL(ucc_fast_enable); | ||
| 113 | 118 | ||
| 114 | void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) | 119 | void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) |
| 115 | { | 120 | { |
| @@ -130,6 +135,7 @@ void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) | |||
| 130 | } | 135 | } |
| 131 | out_be32(&uf_regs->gumr, gumr); | 136 | out_be32(&uf_regs->gumr, gumr); |
| 132 | } | 137 | } |
| 138 | EXPORT_SYMBOL(ucc_fast_disable); | ||
| 133 | 139 | ||
| 134 | int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) | 140 | int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) |
| 135 | { | 141 | { |
| @@ -341,6 +347,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc | |||
| 341 | *uccf_ret = uccf; | 347 | *uccf_ret = uccf; |
| 342 | return 0; | 348 | return 0; |
| 343 | } | 349 | } |
| 350 | EXPORT_SYMBOL(ucc_fast_init); | ||
| 344 | 351 | ||
| 345 | void ucc_fast_free(struct ucc_fast_private * uccf) | 352 | void ucc_fast_free(struct ucc_fast_private * uccf) |
| 346 | { | 353 | { |
| @@ -355,3 +362,4 @@ void ucc_fast_free(struct ucc_fast_private * uccf) | |||
| 355 | 362 | ||
| 356 | kfree(uccf); | 363 | kfree(uccf); |
| 357 | } | 364 | } |
| 365 | EXPORT_SYMBOL(ucc_fast_free); | ||
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c new file mode 100644 index 000000000000..e276048b8c5f --- /dev/null +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * Setup code for PC-style Real-Time Clock. | ||
| 3 | * | ||
| 4 | * Author: Wade Farnsworth <wfarnsworth@mvista.com> | ||
| 5 | * | ||
| 6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
| 7 | * the terms of the GNU General Public License version 2. This program | ||
| 8 | * is licensed "as is" without any warranty of any kind, whether express | ||
| 9 | * or implied. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/mc146818rtc.h> | ||
| 16 | |||
| 17 | #include <asm/prom.h> | ||
| 18 | |||
| 19 | static int __init add_rtc(void) | ||
| 20 | { | ||
| 21 | struct device_node *np; | ||
| 22 | struct platform_device *pd; | ||
| 23 | struct resource res; | ||
| 24 | int ret; | ||
| 25 | |||
| 26 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00"); | ||
| 27 | if (!np) | ||
| 28 | return -ENODEV; | ||
| 29 | |||
| 30 | ret = of_address_to_resource(np, 0, &res); | ||
| 31 | of_node_put(np); | ||
| 32 | if (ret) | ||
| 33 | return ret; | ||
| 34 | |||
| 35 | /* | ||
| 36 | * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h. Verify that the | ||
| 37 | * address provided by the device node matches. | ||
| 38 | */ | ||
| 39 | if (res.start != RTC_PORT(0)) | ||
| 40 | return -EINVAL; | ||
| 41 | |||
| 42 | pd = platform_device_register_simple("rtc_cmos", -1, | ||
| 43 | &res, 1); | ||
| 44 | if (IS_ERR(pd)) | ||
| 45 | return PTR_ERR(pd); | ||
| 46 | |||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | fs_initcall(add_rtc); | ||
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c index 4a01748b4217..e81e7ec2e799 100644 --- a/arch/powerpc/sysdev/timer.c +++ b/arch/powerpc/sysdev/timer.c | |||
| @@ -24,7 +24,12 @@ static int timer_resume(struct sys_device *dev) | |||
| 24 | 24 | ||
| 25 | /* get current RTC time and convert to seconds */ | 25 | /* get current RTC time and convert to seconds */ |
| 26 | get_rtc_time(&cur_rtc_tm); | 26 | get_rtc_time(&cur_rtc_tm); |
| 27 | rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); | 27 | cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900, |
| 28 | cur_rtc_tm.tm_mon + 1, | ||
| 29 | cur_rtc_tm.tm_mday, | ||
| 30 | cur_rtc_tm.tm_hour, | ||
| 31 | cur_rtc_tm.tm_min, | ||
| 32 | cur_rtc_tm.tm_sec); | ||
| 28 | 33 | ||
| 29 | diff = cur_rtc_time - suspend_rtc_time; | 34 | diff = cur_rtc_time - suspend_rtc_time; |
| 30 | 35 | ||
| @@ -44,7 +49,12 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state) | |||
| 44 | WARN_ON(!ppc_md.get_rtc_time); | 49 | WARN_ON(!ppc_md.get_rtc_time); |
| 45 | 50 | ||
| 46 | get_rtc_time(&suspend_rtc_tm); | 51 | get_rtc_time(&suspend_rtc_tm); |
| 47 | rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); | 52 | suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900, |
| 53 | suspend_rtc_tm.tm_mon + 1, | ||
| 54 | suspend_rtc_tm.tm_mday, | ||
| 55 | suspend_rtc_tm.tm_hour, | ||
| 56 | suspend_rtc_tm.tm_min, | ||
| 57 | suspend_rtc_tm.tm_sec); | ||
| 48 | 58 | ||
| 49 | return 0; | 59 | return 0; |
| 50 | } | 60 | } |
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 7d3b09b7d544..a113d800cbf0 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c | |||
| @@ -72,12 +72,11 @@ static int __init tsi108_eth_of_init(void) | |||
| 72 | int ret; | 72 | int ret; |
| 73 | 73 | ||
| 74 | for (np = NULL, i = 0; | 74 | for (np = NULL, i = 0; |
| 75 | (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL; | 75 | (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL; |
| 76 | i++) { | 76 | i++) { |
| 77 | struct resource r[2]; | 77 | struct resource r[2]; |
| 78 | struct device_node *phy; | 78 | struct device_node *phy, *mdio; |
| 79 | hw_info tsi_eth_data; | 79 | hw_info tsi_eth_data; |
| 80 | const unsigned int *id; | ||
| 81 | const unsigned int *phy_id; | 80 | const unsigned int *phy_id; |
| 82 | const void *mac_addr; | 81 | const void *mac_addr; |
| 83 | const phandle *ph; | 82 | const phandle *ph; |
| @@ -111,6 +110,13 @@ static int __init tsi108_eth_of_init(void) | |||
| 111 | if (mac_addr) | 110 | if (mac_addr) |
| 112 | memcpy(tsi_eth_data.mac_addr, mac_addr, 6); | 111 | memcpy(tsi_eth_data.mac_addr, mac_addr, 6); |
| 113 | 112 | ||
| 113 | ph = of_get_property(np, "mdio-handle", NULL); | ||
| 114 | mdio = of_find_node_by_phandle(*ph); | ||
| 115 | ret = of_address_to_resource(mdio, 0, &res); | ||
| 116 | of_node_put(mdio); | ||
| 117 | if (ret) | ||
| 118 | goto unreg; | ||
| 119 | |||
| 114 | ph = of_get_property(np, "phy-handle", NULL); | 120 | ph = of_get_property(np, "phy-handle", NULL); |
| 115 | phy = of_find_node_by_phandle(*ph); | 121 | phy = of_find_node_by_phandle(*ph); |
| 116 | 122 | ||
| @@ -119,20 +125,25 @@ static int __init tsi108_eth_of_init(void) | |||
| 119 | goto unreg; | 125 | goto unreg; |
| 120 | } | 126 | } |
| 121 | 127 | ||
| 122 | id = of_get_property(phy, "reg", NULL); | 128 | phy_id = of_get_property(phy, "reg", NULL); |
| 123 | phy_id = of_get_property(phy, "phy-id", NULL); | 129 | |
| 124 | ret = of_address_to_resource(phy, 0, &res); | ||
| 125 | if (ret) { | ||
| 126 | of_node_put(phy); | ||
| 127 | goto unreg; | ||
| 128 | } | ||
| 129 | tsi_eth_data.regs = r[0].start; | 130 | tsi_eth_data.regs = r[0].start; |
| 130 | tsi_eth_data.phyregs = res.start; | 131 | tsi_eth_data.phyregs = res.start; |
| 131 | tsi_eth_data.phy = *phy_id; | 132 | tsi_eth_data.phy = *phy_id; |
| 132 | tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); | 133 | tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); |
| 133 | if (of_device_is_compatible(phy, "bcm54xx")) | 134 | |
| 135 | /* Some boards with the TSI108 bridge (e.g. Holly) | ||
| 136 | * have a miswiring of the ethernet PHYs which | ||
| 137 | * requires a workaround. The special | ||
| 138 | * "txc-rxc-delay-disable" property enables this | ||
| 139 | * workaround. FIXME: Need to port the tsi108_eth | ||
| 140 | * driver itself to phylib and use a non-misleading | ||
| 141 | * name for the workaround flag - it's not actually to | ||
| 142 | * do with the model of PHY in use */ | ||
| 143 | if (of_get_property(phy, "txc-rxc-delay-disable", NULL)) | ||
| 134 | tsi_eth_data.phy_type = TSI108_PHY_BCM54XX; | 144 | tsi_eth_data.phy_type = TSI108_PHY_BCM54XX; |
| 135 | of_node_put(phy); | 145 | of_node_put(phy); |
| 146 | |||
| 136 | ret = | 147 | ret = |
| 137 | platform_device_add_data(tsi_eth_dev, &tsi_eth_data, | 148 | platform_device_add_data(tsi_eth_dev, &tsi_eth_data, |
| 138 | sizeof(hw_info)); | 149 | sizeof(hw_info)); |
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 2153163fa593..90db8a720fed 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c | |||
| @@ -64,9 +64,10 @@ tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc, | |||
| 64 | int offset, int len, u32 val) | 64 | int offset, int len, u32 val) |
| 65 | { | 65 | { |
| 66 | volatile unsigned char *cfg_addr; | 66 | volatile unsigned char *cfg_addr; |
| 67 | struct pci_controller *hose = bus->sysdata; | ||
| 67 | 68 | ||
| 68 | if (ppc_md.pci_exclude_device) | 69 | if (ppc_md.pci_exclude_device) |
| 69 | if (ppc_md.pci_exclude_device(bus->number, devfunc)) | 70 | if (ppc_md.pci_exclude_device(hose, bus->number, devfunc)) |
| 70 | return PCIBIOS_DEVICE_NOT_FOUND; | 71 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 71 | 72 | ||
| 72 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, | 73 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, |
| @@ -149,10 +150,11 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
| 149 | int len, u32 * val) | 150 | int len, u32 * val) |
| 150 | { | 151 | { |
| 151 | volatile unsigned char *cfg_addr; | 152 | volatile unsigned char *cfg_addr; |
| 153 | struct pci_controller *hose = bus->sysdata; | ||
| 152 | u32 temp; | 154 | u32 temp; |
| 153 | 155 | ||
| 154 | if (ppc_md.pci_exclude_device) | 156 | if (ppc_md.pci_exclude_device) |
| 155 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 157 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
| 156 | return PCIBIOS_DEVICE_NOT_FOUND; | 158 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 157 | 159 | ||
| 158 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, | 160 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, |
| @@ -219,14 +221,12 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) | |||
| 219 | " bus 0\n", dev->full_name); | 221 | " bus 0\n", dev->full_name); |
| 220 | } | 222 | } |
| 221 | 223 | ||
| 222 | hose = pcibios_alloc_controller(); | 224 | hose = pcibios_alloc_controller(dev); |
| 223 | 225 | ||
| 224 | if (!hose) { | 226 | if (!hose) { |
| 225 | printk("PCI Host bridge init failed\n"); | 227 | printk("PCI Host bridge init failed\n"); |
| 226 | return -ENOMEM; | 228 | return -ENOMEM; |
| 227 | } | 229 | } |
| 228 | hose->arch_data = dev; | ||
| 229 | hose->set_cfg_type = 1; | ||
| 230 | 230 | ||
| 231 | hose->first_busno = bus_range ? bus_range[0] : 0; | 231 | hose->first_busno = bus_range ? bus_range[0] : 0; |
| 232 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 232 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 28fdf4f50c27..669e6566ad70 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -2634,7 +2634,7 @@ static int __init setup_xmon_sysrq(void) | |||
| 2634 | __initcall(setup_xmon_sysrq); | 2634 | __initcall(setup_xmon_sysrq); |
| 2635 | #endif /* CONFIG_MAGIC_SYSRQ */ | 2635 | #endif /* CONFIG_MAGIC_SYSRQ */ |
| 2636 | 2636 | ||
| 2637 | int __initdata xmon_early, xmon_off; | 2637 | static int __initdata xmon_early, xmon_off; |
| 2638 | 2638 | ||
| 2639 | static int __init early_parse_xmon(char *p) | 2639 | static int __init early_parse_xmon(char *p) |
| 2640 | { | 2640 | { |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index d319f9ba2379..0da55368655c 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
| @@ -328,7 +328,7 @@ BEGIN_FTR_SECTION | |||
| 328 | mtspr SPRN_L1CSR0,r3 | 328 | mtspr SPRN_L1CSR0,r3 |
| 329 | isync | 329 | isync |
| 330 | blr | 330 | blr |
| 331 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 331 | END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) |
| 332 | mfspr r3,SPRN_L1CSR1 | 332 | mfspr r3,SPRN_L1CSR1 |
| 333 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | 333 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR |
| 334 | mtspr SPRN_L1CSR1,r3 | 334 | mtspr SPRN_L1CSR1,r3 |
| @@ -355,7 +355,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
| 355 | _GLOBAL(__flush_icache_range) | 355 | _GLOBAL(__flush_icache_range) |
| 356 | BEGIN_FTR_SECTION | 356 | BEGIN_FTR_SECTION |
| 357 | blr /* for 601, do nothing */ | 357 | blr /* for 601, do nothing */ |
| 358 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 358 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 359 | li r5,L1_CACHE_BYTES-1 | 359 | li r5,L1_CACHE_BYTES-1 |
| 360 | andc r3,r3,r5 | 360 | andc r3,r3,r5 |
| 361 | subf r4,r3,r4 | 361 | subf r4,r3,r4 |
| @@ -472,7 +472,7 @@ _GLOBAL(flush_dcache_all) | |||
| 472 | _GLOBAL(__flush_dcache_icache) | 472 | _GLOBAL(__flush_dcache_icache) |
| 473 | BEGIN_FTR_SECTION | 473 | BEGIN_FTR_SECTION |
| 474 | blr /* for 601, do nothing */ | 474 | blr /* for 601, do nothing */ |
| 475 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 475 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 476 | rlwinm r3,r3,0,0,19 /* Get page base address */ | 476 | rlwinm r3,r3,0,0,19 /* Get page base address */ |
| 477 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ | 477 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ |
| 478 | mtctr r4 | 478 | mtctr r4 |
| @@ -500,7 +500,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
| 500 | _GLOBAL(__flush_dcache_icache_phys) | 500 | _GLOBAL(__flush_dcache_icache_phys) |
| 501 | BEGIN_FTR_SECTION | 501 | BEGIN_FTR_SECTION |
| 502 | blr /* for 601, do nothing */ | 502 | blr /* for 601, do nothing */ |
| 503 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 503 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
| 504 | mfmsr r10 | 504 | mfmsr r10 |
| 505 | rlwinm r0,r10,0,28,26 /* clear DR */ | 505 | rlwinm r0,r10,0,28,26 /* clear DR */ |
| 506 | mtmsr r0 | 506 | mtmsr r0 |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index a4165209ac7c..63f0a987139b 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
| @@ -64,7 +64,6 @@ extern unsigned long mm_ptov (unsigned long paddr); | |||
| 64 | 64 | ||
| 65 | EXPORT_SYMBOL(clear_pages); | 65 | EXPORT_SYMBOL(clear_pages); |
| 66 | EXPORT_SYMBOL(clear_user_page); | 66 | EXPORT_SYMBOL(clear_user_page); |
| 67 | EXPORT_SYMBOL(do_signal); | ||
| 68 | EXPORT_SYMBOL(transfer_to_handler); | 67 | EXPORT_SYMBOL(transfer_to_handler); |
| 69 | EXPORT_SYMBOL(do_IRQ); | 68 | EXPORT_SYMBOL(do_IRQ); |
| 70 | EXPORT_SYMBOL(machine_check_exception); | 69 | EXPORT_SYMBOL(machine_check_exception); |
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index c79704f5409c..967c1ef59a6b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c | |||
| @@ -526,7 +526,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 526 | * Systems with OF can look in the properties on the cpu node(s) | 526 | * Systems with OF can look in the properties on the cpu node(s) |
| 527 | * for a possibly more accurate value. | 527 | * for a possibly more accurate value. |
| 528 | */ | 528 | */ |
| 529 | if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { | 529 | if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) { |
| 530 | dcache_bsize = cur_cpu_spec->dcache_bsize; | 530 | dcache_bsize = cur_cpu_spec->dcache_bsize; |
| 531 | icache_bsize = cur_cpu_spec->icache_bsize; | 531 | icache_bsize = cur_cpu_spec->icache_bsize; |
| 532 | ucache_bsize = 0; | 532 | ucache_bsize = 0; |
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c index fa29740a28f5..4ff260bc9dd1 100644 --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 29 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
| 30 | #include <linux/pagemap.h> | ||
| 30 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
| 31 | #include <asm/tlb.h> | 32 | #include <asm/tlb.h> |
| 32 | 33 | ||
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 6f21110a9747..3c56654bfc6f 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c | |||
| @@ -69,9 +69,6 @@ | |||
| 69 | 69 | ||
| 70 | TODC_ALLOC(); | 70 | TODC_ALLOC(); |
| 71 | 71 | ||
| 72 | unsigned char ucBoardRev; | ||
| 73 | unsigned char ucBoardRevMaj, ucBoardRevMin; | ||
| 74 | |||
| 75 | extern unsigned char prep_nvram_read_val(int addr); | 72 | extern unsigned char prep_nvram_read_val(int addr); |
| 76 | extern void prep_nvram_write_val(int addr, | 73 | extern void prep_nvram_write_val(int addr, |
| 77 | unsigned char val); | 74 | unsigned char val); |
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 95694159b226..543795be58c8 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile | |||
| @@ -7,6 +7,7 @@ CFLAGS_btext.o += -fPIC | |||
| 7 | 7 | ||
| 8 | wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o | 8 | wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o |
| 9 | 9 | ||
| 10 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
| 10 | obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o | 11 | obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o |
| 11 | obj-$(CONFIG_PPC_OCP) += ocp.o | 12 | obj-$(CONFIG_PPC_OCP) += ocp.o |
| 12 | obj-$(CONFIG_IBM_OCP) += ibm_ocp.o | 13 | obj-$(CONFIG_IBM_OCP) += ibm_ocp.o |
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c new file mode 100644 index 000000000000..83b323a7d029 --- /dev/null +++ b/arch/ppc/syslib/indirect_pci.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* | ||
| 2 | * Support for indirect PCI bridges. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998 Gabriel Paubert. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/pci.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/string.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | |||
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/prom.h> | ||
| 20 | #include <asm/pci-bridge.h> | ||
| 21 | #include <asm/machdep.h> | ||
| 22 | |||
| 23 | #ifdef CONFIG_PPC_INDIRECT_PCI_BE | ||
| 24 | #define PCI_CFG_OUT out_be32 | ||
| 25 | #else | ||
| 26 | #define PCI_CFG_OUT out_le32 | ||
| 27 | #endif | ||
| 28 | |||
| 29 | static int | ||
| 30 | indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 31 | int len, u32 *val) | ||
| 32 | { | ||
| 33 | struct pci_controller *hose = bus->sysdata; | ||
| 34 | volatile void __iomem *cfg_data; | ||
| 35 | u8 cfg_type = 0; | ||
| 36 | |||
| 37 | if (ppc_md.pci_exclude_device) | ||
| 38 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
| 39 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 40 | |||
| 41 | if (hose->set_cfg_type) | ||
| 42 | if (bus->number != hose->first_busno) | ||
| 43 | cfg_type = 1; | ||
| 44 | |||
| 45 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 46 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | ||
| 47 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Note: the caller has already checked that offset is | ||
| 51 | * suitably aligned and that len is 1, 2 or 4. | ||
| 52 | */ | ||
| 53 | cfg_data = hose->cfg_data + (offset & 3); | ||
| 54 | switch (len) { | ||
| 55 | case 1: | ||
| 56 | *val = in_8(cfg_data); | ||
| 57 | break; | ||
| 58 | case 2: | ||
| 59 | *val = in_le16(cfg_data); | ||
| 60 | break; | ||
| 61 | default: | ||
| 62 | *val = in_le32(cfg_data); | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | return PCIBIOS_SUCCESSFUL; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int | ||
| 69 | indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 70 | int len, u32 val) | ||
| 71 | { | ||
| 72 | struct pci_controller *hose = bus->sysdata; | ||
| 73 | volatile void __iomem *cfg_data; | ||
| 74 | u8 cfg_type = 0; | ||
| 75 | |||
| 76 | if (ppc_md.pci_exclude_device) | ||
| 77 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
| 78 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 79 | |||
| 80 | if (hose->set_cfg_type) | ||
| 81 | if (bus->number != hose->first_busno) | ||
| 82 | cfg_type = 1; | ||
| 83 | |||
| 84 | PCI_CFG_OUT(hose->cfg_addr, | ||
| 85 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | ||
| 86 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | ||
| 87 | |||
| 88 | /* | ||
| 89 | * Note: the caller has already checked that offset is | ||
| 90 | * suitably aligned and that len is 1, 2 or 4. | ||
| 91 | */ | ||
| 92 | cfg_data = hose->cfg_data + (offset & 3); | ||
| 93 | switch (len) { | ||
| 94 | case 1: | ||
| 95 | out_8(cfg_data, val); | ||
| 96 | break; | ||
| 97 | case 2: | ||
| 98 | out_le16(cfg_data, val); | ||
| 99 | break; | ||
| 100 | default: | ||
| 101 | out_le32(cfg_data, val); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | return PCIBIOS_SUCCESSFUL; | ||
| 105 | } | ||
| 106 | |||
| 107 | static struct pci_ops indirect_pci_ops = | ||
| 108 | { | ||
| 109 | indirect_read_config, | ||
| 110 | indirect_write_config | ||
| 111 | }; | ||
| 112 | |||
| 113 | void __init | ||
| 114 | setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr, | ||
| 115 | void __iomem * cfg_data) | ||
| 116 | { | ||
| 117 | hose->cfg_addr = cfg_addr; | ||
| 118 | hose->cfg_data = cfg_data; | ||
| 119 | hose->ops = &indirect_pci_ops; | ||
| 120 | } | ||
| 121 | |||
| 122 | void __init | ||
| 123 | setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) | ||
| 124 | { | ||
| 125 | unsigned long base = cfg_addr & PAGE_MASK; | ||
| 126 | void __iomem *mbase, *addr, *data; | ||
| 127 | |||
| 128 | mbase = ioremap(base, PAGE_SIZE); | ||
| 129 | addr = mbase + (cfg_addr & ~PAGE_MASK); | ||
| 130 | if ((cfg_data & PAGE_MASK) != base) | ||
| 131 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); | ||
| 132 | data = mbase + (cfg_data & ~PAGE_MASK); | ||
| 133 | setup_indirect_pci_nomap(hose, addr, data); | ||
| 134 | } | ||
diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c index 16546788e23b..ace4ec08de51 100644 --- a/arch/ppc/syslib/virtex_devices.c +++ b/arch/ppc/syslib/virtex_devices.c | |||
| @@ -71,6 +71,21 @@ | |||
| 71 | }, \ | 71 | }, \ |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /* | ||
| 75 | * ML300/ML403 Video Device: shortcut macro for single instance | ||
| 76 | */ | ||
| 77 | #define XPAR_TFT(num) { \ | ||
| 78 | .name = "xilinxfb", \ | ||
| 79 | .id = num, \ | ||
| 80 | .num_resources = 1, \ | ||
| 81 | .resource = (struct resource[]) { \ | ||
| 82 | { \ | ||
| 83 | .start = XPAR_TFT_##num##_BASEADDR, \ | ||
| 84 | .end = XPAR_TFT_##num##_BASEADDR+7, \ | ||
| 85 | .flags = IORESOURCE_IO, \ | ||
| 86 | }, \ | ||
| 87 | }, \ | ||
| 88 | } | ||
| 74 | 89 | ||
| 75 | /* UART 8250 driver platform data table */ | 90 | /* UART 8250 driver platform data table */ |
| 76 | struct plat_serial8250_port virtex_serial_platform_data[] = { | 91 | struct plat_serial8250_port virtex_serial_platform_data[] = { |
| @@ -146,20 +161,17 @@ struct platform_device virtex_platform_devices[] = { | |||
| 146 | XPAR_SYSACE(1), | 161 | XPAR_SYSACE(1), |
| 147 | #endif | 162 | #endif |
| 148 | 163 | ||
| 149 | /* ML300/403 reference design framebuffer */ | ||
| 150 | #if defined(XPAR_TFT_0_BASEADDR) | 164 | #if defined(XPAR_TFT_0_BASEADDR) |
| 151 | { | 165 | XPAR_TFT(0), |
| 152 | .name = "xilinxfb", | 166 | #endif |
| 153 | .id = 0, | 167 | #if defined(XPAR_TFT_1_BASEADDR) |
| 154 | .num_resources = 1, | 168 | XPAR_TFT(1), |
| 155 | .resource = (struct resource[]) { | 169 | #endif |
| 156 | { | 170 | #if defined(XPAR_TFT_2_BASEADDR) |
| 157 | .start = XPAR_TFT_0_BASEADDR, | 171 | XPAR_TFT(2), |
| 158 | .end = XPAR_TFT_0_BASEADDR+7, | 172 | #endif |
| 159 | .flags = IORESOURCE_IO, | 173 | #if defined(XPAR_TFT_3_BASEADDR) |
| 160 | }, | 174 | XPAR_TFT(3), |
| 161 | }, | ||
| 162 | }, | ||
| 163 | #endif | 175 | #endif |
| 164 | }; | 176 | }; |
| 165 | 177 | ||
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 68592c336011..dae39911a11d 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
| @@ -252,10 +252,10 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
| 252 | struct gendisk *disk = bdev->bd_disk; | 252 | struct gendisk *disk = bdev->bd_disk; |
| 253 | struct viodasd_device *d = disk->private_data; | 253 | struct viodasd_device *d = disk->private_data; |
| 254 | 254 | ||
| 255 | geo->sectors = d->sectors ? d->sectors : 0; | 255 | geo->sectors = d->sectors ? d->sectors : 32; |
| 256 | geo->heads = d->tracks ? d->tracks : 64; | 256 | geo->heads = d->tracks ? d->tracks : 64; |
| 257 | geo->cylinders = d->cylinders ? d->cylinders : | 257 | geo->cylinders = d->cylinders ? d->cylinders : |
| 258 | get_capacity(disk) / (geo->cylinders * geo->heads); | 258 | get_capacity(disk) / (geo->sectors * geo->heads); |
| 259 | 259 | ||
| 260 | return 0; | 260 | return 0; |
| 261 | } | 261 | } |
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index ed53f541d9e8..b6f2639f903d 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
| @@ -91,11 +91,6 @@ static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count | |||
| 91 | unsigned short c; | 91 | unsigned short c; |
| 92 | unsigned char cp; | 92 | unsigned char cp; |
| 93 | 93 | ||
| 94 | #if 0 /* Can't seek (pread) on this device */ | ||
| 95 | if (ppos != &file->f_pos) | ||
| 96 | return -ESPIPE; | ||
| 97 | #endif | ||
| 98 | |||
| 99 | if (!vfd_is_open) | 94 | if (!vfd_is_open) |
| 100 | return -ENODEV; | 95 | return -ENODEV; |
| 101 | 96 | ||
| @@ -139,11 +134,6 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_ | |||
| 139 | size_t indx = len; | 134 | size_t indx = len; |
| 140 | int i, esc = 0; | 135 | int i, esc = 0; |
| 141 | 136 | ||
| 142 | #if 0 /* Can't seek (pwrite) on this device */ | ||
| 143 | if (ppos != &file->f_pos) | ||
| 144 | return -ESPIPE; | ||
| 145 | #endif | ||
| 146 | |||
| 147 | if (!vfd_is_open) | 137 | if (!vfd_is_open) |
| 148 | return -EBUSY; | 138 | return -EBUSY; |
| 149 | 139 | ||
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 322bc5f7d86b..b3ab42e0dd4a 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -674,7 +674,7 @@ static const cpumask_t cpus_in_xmon = CPU_MASK_NONE; | |||
| 674 | * calling hvc_poll() who determines whether a console adapter support | 674 | * calling hvc_poll() who determines whether a console adapter support |
| 675 | * interrupts. | 675 | * interrupts. |
| 676 | */ | 676 | */ |
| 677 | int khvcd(void *unused) | 677 | static int khvcd(void *unused) |
| 678 | { | 678 | { |
| 679 | int poll_mask; | 679 | int poll_mask; |
| 680 | struct hvc_struct *hp; | 680 | struct hvc_struct *hp; |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 13faf8d17482..db57277117bb 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
| @@ -873,12 +873,12 @@ free_op: | |||
| 873 | } | 873 | } |
| 874 | 874 | ||
| 875 | const struct file_operations viotap_fops = { | 875 | const struct file_operations viotap_fops = { |
| 876 | owner: THIS_MODULE, | 876 | .owner = THIS_MODULE, |
| 877 | read: viotap_read, | 877 | .read = viotap_read, |
| 878 | write: viotap_write, | 878 | .write = viotap_write, |
| 879 | ioctl: viotap_ioctl, | 879 | .ioctl = viotap_ioctl, |
| 880 | open: viotap_open, | 880 | .open = viotap_open, |
| 881 | release: viotap_release, | 881 | .release = viotap_release, |
| 882 | }; | 882 | }; |
| 883 | 883 | ||
| 884 | /* Handle interrupt events for tape */ | 884 | /* Handle interrupt events for tape */ |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index bb3c101c2c5a..deb6b5e35feb 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
| @@ -159,8 +159,8 @@ static void dlpar_pci_add_bus(struct device_node *dn) | |||
| 159 | /* Claim new bus resources */ | 159 | /* Claim new bus resources */ |
| 160 | pcibios_claim_one_bus(dev->bus); | 160 | pcibios_claim_one_bus(dev->bus); |
| 161 | 161 | ||
| 162 | /* ioremap() for child bus, which may or may not succeed */ | 162 | /* Map IO space for child bus, which may or may not succeed */ |
| 163 | remap_bus_range(dev->subordinate); | 163 | pcibios_map_io_space(dev->subordinate); |
| 164 | 164 | ||
| 165 | /* Add new devices to global lists. Register in proc, sysfs. */ | 165 | /* Add new devices to global lists. Register in proc, sysfs. */ |
| 166 | pci_bus_add_devices(phb->bus); | 166 | pci_bus_add_devices(phb->bus); |
| @@ -390,7 +390,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 390 | } else | 390 | } else |
| 391 | pcibios_remove_pci_devices(bus); | 391 | pcibios_remove_pci_devices(bus); |
| 392 | 392 | ||
| 393 | if (unmap_bus_range(bus)) { | 393 | if (pcibios_unmap_io_space(bus)) { |
| 394 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 394 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
| 395 | __FUNCTION__); | 395 | __FUNCTION__); |
| 396 | return -ERANGE; | 396 | return -ERANGE; |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 35f88649d3b7..c0c77f82d051 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
| @@ -180,14 +180,15 @@ config TCIC | |||
| 180 | PCMCIA cards are plugged into. If unsure, say N. | 180 | PCMCIA cards are plugged into. If unsure, say N. |
| 181 | 181 | ||
| 182 | config PCMCIA_M8XX | 182 | config PCMCIA_M8XX |
| 183 | tristate "MPC8xx PCMCIA support" | 183 | tristate "MPC8xx PCMCIA support" |
| 184 | depends on PCMCIA && PPC && 8xx | 184 | depends on PCMCIA && PPC && 8xx |
| 185 | select PCCARD_IODYN | 185 | select PCCARD_IODYN |
| 186 | help | 186 | select PCCARD_NONSTATIC |
| 187 | Say Y here to include support for PowerPC 8xx series PCMCIA | 187 | help |
| 188 | controller. | 188 | Say Y here to include support for PowerPC 8xx series PCMCIA |
| 189 | 189 | controller. | |
| 190 | This driver is also available as a module called m8xx_pcmcia. | 190 | |
| 191 | This driver is also available as a module called m8xx_pcmcia. | ||
| 191 | 192 | ||
| 192 | config HD64465_PCMCIA | 193 | config HD64465_PCMCIA |
| 193 | tristate "HD64465 host bridge support" | 194 | tristate "HD64465 host bridge support" |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 9721ed7bf502..3b40f9623cc9 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | * Further fixes, v2.6 kernel port | 10 | * Further fixes, v2.6 kernel port |
| 11 | * <marcelo.tosatti@cyclades.com> | 11 | * <marcelo.tosatti@cyclades.com> |
| 12 | * | 12 | * |
| 13 | * Some fixes, additions (C) 2005 Montavista Software, Inc. | 13 | * Some fixes, additions (C) 2005-2007 Montavista Software, Inc. |
| 14 | * <vbordug@ru.mvista.com> | 14 | * <vbordug@ru.mvista.com> |
| 15 | * | 15 | * |
| 16 | * "The ExCA standard specifies that socket controllers should provide | 16 | * "The ExCA standard specifies that socket controllers should provide |
| @@ -40,10 +40,6 @@ | |||
| 40 | #include <linux/fcntl.h> | 40 | #include <linux/fcntl.h> |
| 41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
| 42 | 42 | ||
| 43 | #include <asm/io.h> | ||
| 44 | #include <asm/bitops.h> | ||
| 45 | #include <asm/system.h> | ||
| 46 | |||
| 47 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
| 48 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
| 49 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
| @@ -51,11 +47,18 @@ | |||
| 51 | #include <linux/ioport.h> | 47 | #include <linux/ioport.h> |
| 52 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
| 53 | #include <linux/interrupt.h> | 49 | #include <linux/interrupt.h> |
| 54 | #include <linux/platform_device.h> | 50 | #include <linux/fsl_devices.h> |
| 55 | 51 | ||
| 52 | #include <asm/io.h> | ||
| 53 | #include <asm/bitops.h> | ||
| 54 | #include <asm/system.h> | ||
| 55 | #include <asm/time.h> | ||
| 56 | #include <asm/mpc8xx.h> | 56 | #include <asm/mpc8xx.h> |
| 57 | #include <asm/8xx_immap.h> | 57 | #include <asm/8xx_immap.h> |
| 58 | #include <asm/irq.h> | 58 | #include <asm/irq.h> |
| 59 | #include <asm/fs_pd.h> | ||
| 60 | #include <asm/of_device.h> | ||
| 61 | #include <asm/of_platform.h> | ||
| 59 | 62 | ||
| 60 | #include <pcmcia/version.h> | 63 | #include <pcmcia/version.h> |
| 61 | #include <pcmcia/cs_types.h> | 64 | #include <pcmcia/cs_types.h> |
| @@ -146,27 +149,17 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
| 146 | #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ | 149 | #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ |
| 147 | #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ | 150 | #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ |
| 148 | #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ | 151 | #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ |
| 149 | |||
| 150 | #define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */ | ||
| 151 | |||
| 152 | /* ------------------------------------------------------------------------- */ | 152 | /* ------------------------------------------------------------------------- */ |
| 153 | 153 | ||
| 154 | /* 2.4.x and newer has this always in HZ */ | 154 | static int pcmcia_schlvl; |
| 155 | #define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq)) | ||
| 156 | |||
| 157 | static int pcmcia_schlvl = PCMCIA_SCHLVL; | ||
| 158 | 155 | ||
| 159 | static DEFINE_SPINLOCK(events_lock); | 156 | static DEFINE_SPINLOCK(events_lock); |
| 160 | 157 | ||
| 161 | |||
| 162 | #define PCMCIA_SOCKET_KEY_5V 1 | 158 | #define PCMCIA_SOCKET_KEY_5V 1 |
| 163 | #define PCMCIA_SOCKET_KEY_LV 2 | 159 | #define PCMCIA_SOCKET_KEY_LV 2 |
| 164 | 160 | ||
| 165 | /* look up table for pgcrx registers */ | 161 | /* look up table for pgcrx registers */ |
| 166 | static u32 *m8xx_pgcrx[2] = { | 162 | static u32 *m8xx_pgcrx[2]; |
| 167 | &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra, | ||
| 168 | &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb | ||
| 169 | }; | ||
| 170 | 163 | ||
| 171 | /* | 164 | /* |
| 172 | * This structure is used to address each window in the PCMCIA controller. | 165 | * This structure is used to address each window in the PCMCIA controller. |
| @@ -228,11 +221,16 @@ struct event_table { | |||
| 228 | u32 eventbit; | 221 | u32 eventbit; |
| 229 | }; | 222 | }; |
| 230 | 223 | ||
| 224 | static const char driver_name[] = "m8xx-pcmcia"; | ||
| 225 | |||
| 231 | struct socket_info { | 226 | struct socket_info { |
| 232 | void (*handler)(void *info, u32 events); | 227 | void (*handler)(void *info, u32 events); |
| 233 | void *info; | 228 | void *info; |
| 234 | 229 | ||
| 235 | u32 slot; | 230 | u32 slot; |
| 231 | pcmconf8xx_t *pcmcia; | ||
| 232 | u32 bus_freq; | ||
| 233 | int hwirq; | ||
| 236 | 234 | ||
| 237 | socket_state_t state; | 235 | socket_state_t state; |
| 238 | struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; | 236 | struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; |
| @@ -408,78 +406,21 @@ static void hardware_disable(int slot) | |||
| 408 | #if defined(CONFIG_MPC885ADS) | 406 | #if defined(CONFIG_MPC885ADS) |
| 409 | 407 | ||
| 410 | #define PCMCIA_BOARD_MSG "MPC885ADS" | 408 | #define PCMCIA_BOARD_MSG "MPC885ADS" |
| 409 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | ||
| 411 | 410 | ||
| 412 | static int voltage_set(int slot, int vcc, int vpp) | 411 | static inline void hardware_enable(int slot) |
| 413 | { | 412 | { |
| 414 | u32 reg = 0; | 413 | m8xx_pcmcia_ops.hw_ctrl(slot, 1); |
| 415 | unsigned *bcsr_io; | ||
| 416 | |||
| 417 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
| 418 | |||
| 419 | switch(vcc) { | ||
| 420 | case 0: | ||
| 421 | break; | ||
| 422 | case 33: | ||
| 423 | reg |= BCSR1_PCCVCC0; | ||
| 424 | break; | ||
| 425 | case 50: | ||
| 426 | reg |= BCSR1_PCCVCC1; | ||
| 427 | break; | ||
| 428 | default: | ||
| 429 | goto out_unmap; | ||
| 430 | } | ||
| 431 | |||
| 432 | switch(vpp) { | ||
| 433 | case 0: | ||
| 434 | break; | ||
| 435 | case 33: | ||
| 436 | case 50: | ||
| 437 | if(vcc == vpp) | ||
| 438 | reg |= BCSR1_PCCVPP1; | ||
| 439 | else | ||
| 440 | goto out_unmap; | ||
| 441 | break; | ||
| 442 | case 120: | ||
| 443 | if ((vcc == 33) || (vcc == 50)) | ||
| 444 | reg |= BCSR1_PCCVPP0; | ||
| 445 | else | ||
| 446 | goto out_unmap; | ||
| 447 | default: | ||
| 448 | goto out_unmap; | ||
| 449 | } | ||
| 450 | |||
| 451 | /* first, turn off all power */ | ||
| 452 | out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); | ||
| 453 | |||
| 454 | /* enable new powersettings */ | ||
| 455 | out_be32(bcsr_io, in_be32(bcsr_io) | reg); | ||
| 456 | |||
| 457 | iounmap(bcsr_io); | ||
| 458 | return 0; | ||
| 459 | |||
| 460 | out_unmap: | ||
| 461 | iounmap(bcsr_io); | ||
| 462 | return 1; | ||
| 463 | } | 414 | } |
| 464 | 415 | ||
| 465 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | 416 | static inline void hardware_disable(int slot) |
| 466 | |||
| 467 | static void hardware_enable(int slot) | ||
| 468 | { | 417 | { |
| 469 | unsigned *bcsr_io; | 418 | m8xx_pcmcia_ops.hw_ctrl(slot, 0); |
| 470 | |||
| 471 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
| 472 | out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN); | ||
| 473 | iounmap(bcsr_io); | ||
| 474 | } | 419 | } |
| 475 | 420 | ||
| 476 | static void hardware_disable(int slot) | 421 | static inline int voltage_set(int slot, int vcc, int vpp) |
| 477 | { | 422 | { |
| 478 | unsigned *bcsr_io; | 423 | return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); |
| 479 | |||
| 480 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
| 481 | out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN); | ||
| 482 | iounmap(bcsr_io); | ||
| 483 | } | 424 | } |
| 484 | 425 | ||
| 485 | #endif | 426 | #endif |
| @@ -604,48 +545,6 @@ static int voltage_set(int slot, int vcc, int vpp) | |||
| 604 | 545 | ||
| 605 | #endif /* CONFIG_PRxK */ | 546 | #endif /* CONFIG_PRxK */ |
| 606 | 547 | ||
| 607 | static void m8xx_shutdown(void) | ||
| 608 | { | ||
| 609 | u32 m, i; | ||
| 610 | struct pcmcia_win *w; | ||
| 611 | |||
| 612 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ | ||
| 613 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | ||
| 614 | |||
| 615 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i)); | ||
| 616 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i)); | ||
| 617 | |||
| 618 | /* turn off interrupt and disable CxOE */ | ||
| 619 | out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); | ||
| 620 | |||
| 621 | /* turn off memory windows */ | ||
| 622 | for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
| 623 | out_be32(&w->or, 0); /* set to not valid */ | ||
| 624 | w++; | ||
| 625 | } | ||
| 626 | |||
| 627 | /* turn off voltage */ | ||
| 628 | voltage_set(i, 0, 0); | ||
| 629 | |||
| 630 | /* disable external hardware */ | ||
| 631 | hardware_disable(i); | ||
| 632 | } | ||
| 633 | |||
| 634 | free_irq(pcmcia_schlvl, NULL); | ||
| 635 | } | ||
| 636 | |||
| 637 | static struct device_driver m8xx_driver = { | ||
| 638 | .name = "m8xx-pcmcia", | ||
| 639 | .bus = &platform_bus_type, | ||
| 640 | .suspend = pcmcia_socket_dev_suspend, | ||
| 641 | .resume = pcmcia_socket_dev_resume, | ||
| 642 | }; | ||
| 643 | |||
| 644 | static struct platform_device m8xx_device = { | ||
| 645 | .name = "m8xx-pcmcia", | ||
| 646 | .id = 0, | ||
| 647 | }; | ||
| 648 | |||
| 649 | static u32 pending_events[PCMCIA_SOCKETS_NO]; | 548 | static u32 pending_events[PCMCIA_SOCKETS_NO]; |
| 650 | static DEFINE_SPINLOCK(pending_event_lock); | 549 | static DEFINE_SPINLOCK(pending_event_lock); |
| 651 | 550 | ||
| @@ -654,13 +553,14 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
| 654 | struct socket_info *s; | 553 | struct socket_info *s; |
| 655 | struct event_table *e; | 554 | struct event_table *e; |
| 656 | unsigned int i, events, pscr, pipr, per; | 555 | unsigned int i, events, pscr, pipr, per; |
| 556 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 657 | 557 | ||
| 658 | dprintk("Interrupt!\n"); | 558 | dprintk("Interrupt!\n"); |
| 659 | /* get interrupt sources */ | 559 | /* get interrupt sources */ |
| 660 | 560 | ||
| 661 | pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr); | 561 | pscr = in_be32(&pcmcia->pcmc_pscr); |
| 662 | pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); | 562 | pipr = in_be32(&pcmcia->pcmc_pipr); |
| 663 | per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per); | 563 | per = in_be32(&pcmcia->pcmc_per); |
| 664 | 564 | ||
| 665 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { | 565 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
| 666 | s = &socket[i]; | 566 | s = &socket[i]; |
| @@ -724,7 +624,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
| 724 | per &= ~M8XX_PCMCIA_RDY_L(0); | 624 | per &= ~M8XX_PCMCIA_RDY_L(0); |
| 725 | per &= ~M8XX_PCMCIA_RDY_L(1); | 625 | per &= ~M8XX_PCMCIA_RDY_L(1); |
| 726 | 626 | ||
| 727 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per); | 627 | out_be32(&pcmcia->pcmc_per, per); |
| 728 | 628 | ||
| 729 | if (events) | 629 | if (events) |
| 730 | pcmcia_parse_events(&socket[i].socket, events); | 630 | pcmcia_parse_events(&socket[i].socket, events); |
| @@ -732,7 +632,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
| 732 | } | 632 | } |
| 733 | 633 | ||
| 734 | /* clear the interrupt sources */ | 634 | /* clear the interrupt sources */ |
| 735 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr); | 635 | out_be32(&pcmcia->pcmc_pscr, pscr); |
| 736 | 636 | ||
| 737 | dprintk("Interrupt done.\n"); | 637 | dprintk("Interrupt done.\n"); |
| 738 | 638 | ||
| @@ -753,7 +653,7 @@ static u32 m8xx_get_graycode(u32 size) | |||
| 753 | return k; | 653 | return k; |
| 754 | } | 654 | } |
| 755 | 655 | ||
| 756 | static u32 m8xx_get_speed(u32 ns, u32 is_io) | 656 | static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) |
| 757 | { | 657 | { |
| 758 | u32 reg, clocks, psst, psl, psht; | 658 | u32 reg, clocks, psst, psl, psht; |
| 759 | 659 | ||
| @@ -781,7 +681,7 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io) | |||
| 781 | 681 | ||
| 782 | #define ADJ 180 /* 80 % longer accesstime - to be sure */ | 682 | #define ADJ 180 /* 80 % longer accesstime - to be sure */ |
| 783 | 683 | ||
| 784 | clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; | 684 | clocks = ((bus_freq / 1000) * ns) / 1000; |
| 785 | clocks = (clocks * ADJ) / (100*1000); | 685 | clocks = (clocks * ADJ) / (100*1000); |
| 786 | if(clocks >= PCMCIA_BMT_LIMIT) { | 686 | if(clocks >= PCMCIA_BMT_LIMIT) { |
| 787 | printk( "Max access time limit reached\n"); | 687 | printk( "Max access time limit reached\n"); |
| @@ -806,8 +706,9 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
| 806 | int lsock = container_of(sock, struct socket_info, socket)->slot; | 706 | int lsock = container_of(sock, struct socket_info, socket)->slot; |
| 807 | struct socket_info *s = &socket[lsock]; | 707 | struct socket_info *s = &socket[lsock]; |
| 808 | unsigned int pipr, reg; | 708 | unsigned int pipr, reg; |
| 709 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 809 | 710 | ||
| 810 | pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); | 711 | pipr = in_be32(&pcmcia->pcmc_pipr); |
| 811 | 712 | ||
| 812 | *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) | 713 | *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) |
| 813 | | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; | 714 | | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; |
| @@ -918,6 +819,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
| 918 | struct event_table *e; | 819 | struct event_table *e; |
| 919 | unsigned int reg; | 820 | unsigned int reg; |
| 920 | unsigned long flags; | 821 | unsigned long flags; |
| 822 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 921 | 823 | ||
| 922 | dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " | 824 | dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " |
| 923 | "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, | 825 | "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, |
| @@ -927,6 +829,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
| 927 | if(voltage_set(lsock, state->Vcc, state->Vpp)) | 829 | if(voltage_set(lsock, state->Vcc, state->Vpp)) |
| 928 | return -EINVAL; | 830 | return -EINVAL; |
| 929 | 831 | ||
| 832 | |||
| 930 | /* Take care of reset... */ | 833 | /* Take care of reset... */ |
| 931 | if(state->flags & SS_RESET) | 834 | if(state->flags & SS_RESET) |
| 932 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ | 835 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ |
| @@ -982,7 +885,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
| 982 | * If io_irq is non-zero we should enable irq. | 885 | * If io_irq is non-zero we should enable irq. |
| 983 | */ | 886 | */ |
| 984 | if(state->io_irq) { | 887 | if(state->io_irq) { |
| 985 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24); | 888 | out_be32(M8XX_PGCRX(lsock), |
| 889 | in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24); | ||
| 986 | /* | 890 | /* |
| 987 | * Strange thing here: | 891 | * Strange thing here: |
| 988 | * The manual does not tell us which interrupt | 892 | * The manual does not tell us which interrupt |
| @@ -1027,7 +931,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
| 1027 | * Writing ones will clear the bits. | 931 | * Writing ones will clear the bits. |
| 1028 | */ | 932 | */ |
| 1029 | 933 | ||
| 1030 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg); | 934 | out_be32(&pcmcia->pcmc_pscr, reg); |
| 1031 | 935 | ||
| 1032 | /* | 936 | /* |
| 1033 | * Write the mask. | 937 | * Write the mask. |
| @@ -1036,15 +940,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
| 1036 | * Ones will enable the interrupt. | 940 | * Ones will enable the interrupt. |
| 1037 | */ | 941 | */ |
| 1038 | 942 | ||
| 1039 | /* | 943 | reg |= in_be32(&pcmcia->pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
| 1040 | reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per | 944 | out_be32(&pcmcia->pcmc_per, reg); |
| 1041 | & M8XX_PCMCIA_MASK(lsock); | ||
| 1042 | */ | ||
| 1043 | |||
| 1044 | reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & | ||
| 1045 | (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); | ||
| 1046 | |||
| 1047 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg); | ||
| 1048 | 945 | ||
| 1049 | spin_unlock_irqrestore(&events_lock, flags); | 946 | spin_unlock_irqrestore(&events_lock, flags); |
| 1050 | 947 | ||
| @@ -1062,6 +959,8 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
| 1062 | struct socket_info *s = &socket[lsock]; | 959 | struct socket_info *s = &socket[lsock]; |
| 1063 | struct pcmcia_win *w; | 960 | struct pcmcia_win *w; |
| 1064 | unsigned int reg, winnr; | 961 | unsigned int reg, winnr; |
| 962 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 963 | |||
| 1065 | 964 | ||
| 1066 | #define M8XX_SIZE (io->stop - io->start + 1) | 965 | #define M8XX_SIZE (io->stop - io->start + 1) |
| 1067 | #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) | 966 | #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) |
| @@ -1086,7 +985,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
| 1086 | 985 | ||
| 1087 | /* setup registers */ | 986 | /* setup registers */ |
| 1088 | 987 | ||
| 1089 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 988 | w = (void *) &pcmcia->pcmc_pbr0; |
| 1090 | w += winnr; | 989 | w += winnr; |
| 1091 | 990 | ||
| 1092 | out_be32(&w->or, 0); /* turn off window first */ | 991 | out_be32(&w->or, 0); /* turn off window first */ |
| @@ -1095,12 +994,13 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
| 1095 | reg <<= 27; | 994 | reg <<= 27; |
| 1096 | reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); | 995 | reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); |
| 1097 | 996 | ||
| 1098 | reg |= m8xx_get_speed(io->speed, 1); | 997 | reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); |
| 1099 | 998 | ||
| 1100 | if(io->flags & MAP_WRPROT) | 999 | if(io->flags & MAP_WRPROT) |
| 1101 | reg |= M8XX_PCMCIA_POR_WRPROT; | 1000 | reg |= M8XX_PCMCIA_POR_WRPROT; |
| 1102 | 1001 | ||
| 1103 | if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) | 1002 | /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/ |
| 1003 | if(io->flags & MAP_16BIT) | ||
| 1104 | reg |= M8XX_PCMCIA_POR_16BIT; | 1004 | reg |= M8XX_PCMCIA_POR_16BIT; |
| 1105 | 1005 | ||
| 1106 | if(io->flags & MAP_ACTIVE) | 1006 | if(io->flags & MAP_ACTIVE) |
| @@ -1117,7 +1017,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
| 1117 | 1017 | ||
| 1118 | /* setup registers */ | 1018 | /* setup registers */ |
| 1119 | 1019 | ||
| 1120 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1020 | w = (void *) &pcmcia->pcmc_pbr0; |
| 1121 | w += winnr; | 1021 | w += winnr; |
| 1122 | 1022 | ||
| 1123 | out_be32(&w->or, 0); /* turn off window */ | 1023 | out_be32(&w->or, 0); /* turn off window */ |
| @@ -1144,6 +1044,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m | |||
| 1144 | struct pcmcia_win *w; | 1044 | struct pcmcia_win *w; |
| 1145 | struct pccard_mem_map *old; | 1045 | struct pccard_mem_map *old; |
| 1146 | unsigned int reg, winnr; | 1046 | unsigned int reg, winnr; |
| 1047 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 1147 | 1048 | ||
| 1148 | dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " | 1049 | dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " |
| 1149 | "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, | 1050 | "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, |
| @@ -1166,12 +1067,12 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m | |||
| 1166 | 1067 | ||
| 1167 | /* Setup the window in the pcmcia controller */ | 1068 | /* Setup the window in the pcmcia controller */ |
| 1168 | 1069 | ||
| 1169 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1070 | w = (void *) &pcmcia->pcmc_pbr0; |
| 1170 | w += winnr; | 1071 | w += winnr; |
| 1171 | 1072 | ||
| 1172 | reg |= lsock << 2; | 1073 | reg |= lsock << 2; |
| 1173 | 1074 | ||
| 1174 | reg |= m8xx_get_speed(mem->speed, 0); | 1075 | reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); |
| 1175 | 1076 | ||
| 1176 | if(mem->flags & MAP_ATTRIB) | 1077 | if(mem->flags & MAP_ATTRIB) |
| 1177 | reg |= M8XX_PCMCIA_POR_ATTRMEM; | 1078 | reg |= M8XX_PCMCIA_POR_ATTRMEM; |
| @@ -1236,60 +1137,69 @@ static int m8xx_sock_init(struct pcmcia_socket *sock) | |||
| 1236 | 1137 | ||
| 1237 | } | 1138 | } |
| 1238 | 1139 | ||
| 1239 | static int m8xx_suspend(struct pcmcia_socket *sock) | 1140 | static int m8xx_sock_suspend(struct pcmcia_socket *sock) |
| 1240 | { | 1141 | { |
| 1241 | return m8xx_set_socket(sock, &dead_socket); | 1142 | return m8xx_set_socket(sock, &dead_socket); |
| 1242 | } | 1143 | } |
| 1243 | 1144 | ||
| 1244 | static struct pccard_operations m8xx_services = { | 1145 | static struct pccard_operations m8xx_services = { |
| 1245 | .init = m8xx_sock_init, | 1146 | .init = m8xx_sock_init, |
| 1246 | .suspend = m8xx_suspend, | 1147 | .suspend = m8xx_sock_suspend, |
| 1247 | .get_status = m8xx_get_status, | 1148 | .get_status = m8xx_get_status, |
| 1248 | .set_socket = m8xx_set_socket, | 1149 | .set_socket = m8xx_set_socket, |
| 1249 | .set_io_map = m8xx_set_io_map, | 1150 | .set_io_map = m8xx_set_io_map, |
| 1250 | .set_mem_map = m8xx_set_mem_map, | 1151 | .set_mem_map = m8xx_set_mem_map, |
| 1251 | }; | 1152 | }; |
| 1252 | 1153 | ||
| 1253 | static int __init m8xx_init(void) | 1154 | static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id *match) |
| 1254 | { | 1155 | { |
| 1255 | struct pcmcia_win *w; | 1156 | struct pcmcia_win *w; |
| 1256 | unsigned int i,m; | 1157 | unsigned int i, m, hwirq; |
| 1158 | pcmconf8xx_t *pcmcia; | ||
| 1159 | int status; | ||
| 1160 | struct device_node *np = ofdev->node; | ||
| 1257 | 1161 | ||
| 1258 | pcmcia_info("%s\n", version); | 1162 | pcmcia_info("%s\n", version); |
| 1259 | 1163 | ||
| 1260 | if (driver_register(&m8xx_driver)) | 1164 | pcmcia = of_iomap(np, 0); |
| 1261 | return -1; | 1165 | if(pcmcia == NULL) |
| 1166 | return -EINVAL; | ||
| 1167 | |||
| 1168 | pcmcia_schlvl = irq_of_parse_and_map(np, 0); | ||
| 1169 | hwirq = irq_map[pcmcia_schlvl].hwirq; | ||
| 1170 | if (pcmcia_schlvl < 0) | ||
| 1171 | return -EINVAL; | ||
| 1172 | |||
| 1173 | m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; | ||
| 1174 | m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; | ||
| 1175 | |||
| 1262 | 1176 | ||
| 1263 | pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG | 1177 | pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG |
| 1264 | " with IRQ %u.\n", pcmcia_schlvl); | 1178 | " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq); |
| 1265 | 1179 | ||
| 1266 | /* Configure Status change interrupt */ | 1180 | /* Configure Status change interrupt */ |
| 1267 | 1181 | ||
| 1268 | if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, | 1182 | if(request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, |
| 1269 | "m8xx_pcmcia", NULL)) { | 1183 | driver_name, socket)) { |
| 1270 | pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", | 1184 | pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", |
| 1271 | pcmcia_schlvl); | 1185 | pcmcia_schlvl); |
| 1272 | return -1; | 1186 | return -1; |
| 1273 | } | 1187 | } |
| 1274 | 1188 | ||
| 1275 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1189 | w = (void *) &pcmcia->pcmc_pbr0; |
| 1276 | |||
| 1277 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, | ||
| 1278 | M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); | ||
| 1279 | 1190 | ||
| 1280 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, | 1191 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); |
| 1281 | in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & | 1192 | clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
| 1282 | ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1))); | ||
| 1283 | 1193 | ||
| 1284 | /* connect interrupt and disable CxOE */ | 1194 | /* connect interrupt and disable CxOE */ |
| 1285 | 1195 | ||
| 1286 | out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); | 1196 | out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
| 1287 | out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); | 1197 | out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
| 1288 | 1198 | ||
| 1289 | /* intialize the fixed memory windows */ | 1199 | /* intialize the fixed memory windows */ |
| 1290 | 1200 | ||
| 1291 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ | 1201 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ |
| 1292 | for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | 1202 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { |
| 1293 | out_be32(&w->br, PCMCIA_MEM_WIN_BASE + | 1203 | out_be32(&w->br, PCMCIA_MEM_WIN_BASE + |
| 1294 | (PCMCIA_MEM_WIN_SIZE | 1204 | (PCMCIA_MEM_WIN_SIZE |
| 1295 | * (m + i * PCMCIA_MEM_WIN_NO))); | 1205 | * (m + i * PCMCIA_MEM_WIN_NO))); |
| @@ -1300,16 +1210,14 @@ static int __init m8xx_init(void) | |||
| 1300 | } | 1210 | } |
| 1301 | } | 1211 | } |
| 1302 | 1212 | ||
| 1303 | /* turn off voltage */ | 1213 | /* turn off voltage */ |
| 1304 | voltage_set(0, 0, 0); | 1214 | voltage_set(0, 0, 0); |
| 1305 | voltage_set(1, 0, 0); | 1215 | voltage_set(1, 0, 0); |
| 1306 | 1216 | ||
| 1307 | /* Enable external hardware */ | 1217 | /* Enable external hardware */ |
| 1308 | hardware_enable(0); | 1218 | hardware_enable(0); |
| 1309 | hardware_enable(1); | 1219 | hardware_enable(1); |
| 1310 | 1220 | ||
| 1311 | platform_device_register(&m8xx_device); | ||
| 1312 | |||
| 1313 | for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { | 1221 | for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { |
| 1314 | socket[i].slot = i; | 1222 | socket[i].slot = i; |
| 1315 | socket[i].socket.owner = THIS_MODULE; | 1223 | socket[i].socket.owner = THIS_MODULE; |
| @@ -1317,30 +1225,105 @@ static int __init m8xx_init(void) | |||
| 1317 | socket[i].socket.irq_mask = 0x000; | 1225 | socket[i].socket.irq_mask = 0x000; |
| 1318 | socket[i].socket.map_size = 0x1000; | 1226 | socket[i].socket.map_size = 0x1000; |
| 1319 | socket[i].socket.io_offset = 0; | 1227 | socket[i].socket.io_offset = 0; |
| 1320 | socket[i].socket.pci_irq = i ? 7 : 9; | 1228 | socket[i].socket.pci_irq = pcmcia_schlvl; |
| 1321 | socket[i].socket.ops = &m8xx_services; | 1229 | socket[i].socket.ops = &m8xx_services; |
| 1322 | socket[i].socket.resource_ops = &pccard_iodyn_ops; | 1230 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
| 1323 | socket[i].socket.cb_dev = NULL; | 1231 | socket[i].socket.cb_dev = NULL; |
| 1324 | socket[i].socket.dev.parent = &m8xx_device.dev; | 1232 | socket[i].socket.dev.parent = &ofdev->dev; |
| 1233 | socket[i].pcmcia = pcmcia; | ||
| 1234 | socket[i].bus_freq = ppc_proc_freq; | ||
| 1235 | socket[i].hwirq = hwirq; | ||
| 1236 | |||
| 1237 | |||
| 1325 | } | 1238 | } |
| 1326 | 1239 | ||
| 1327 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) | 1240 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
| 1328 | pcmcia_register_socket(&socket[i].socket); | 1241 | status = pcmcia_register_socket(&socket[i].socket); |
| 1242 | if (status < 0) | ||
| 1243 | pcmcia_error("Socket register failed\n"); | ||
| 1244 | } | ||
| 1329 | 1245 | ||
| 1330 | return 0; | 1246 | return 0; |
| 1331 | } | 1247 | } |
| 1332 | 1248 | ||
| 1333 | static void __exit m8xx_exit(void) | 1249 | static int m8xx_remove(struct of_device* ofdev) |
| 1334 | { | 1250 | { |
| 1335 | int i; | 1251 | u32 m, i; |
| 1252 | struct pcmcia_win *w; | ||
| 1253 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 1254 | |||
| 1255 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 1256 | w = (void *) &pcmcia->pcmc_pbr0; | ||
| 1257 | |||
| 1258 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); | ||
| 1259 | out_be32(&pcmcia->pcmc_per, | ||
| 1260 | in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); | ||
| 1336 | 1261 | ||
| 1262 | /* turn off interrupt and disable CxOE */ | ||
| 1263 | out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); | ||
| 1264 | |||
| 1265 | /* turn off memory windows */ | ||
| 1266 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
| 1267 | out_be32(&w->or, 0); /* set to not valid */ | ||
| 1268 | w++; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | /* turn off voltage */ | ||
| 1272 | voltage_set(i, 0, 0); | ||
| 1273 | |||
| 1274 | /* disable external hardware */ | ||
| 1275 | hardware_disable(i); | ||
| 1276 | } | ||
| 1337 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) | 1277 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) |
| 1338 | pcmcia_unregister_socket(&socket[i].socket); | 1278 | pcmcia_unregister_socket(&socket[i].socket); |
| 1339 | 1279 | ||
| 1340 | m8xx_shutdown(); | 1280 | free_irq(pcmcia_schlvl, NULL); |
| 1341 | 1281 | ||
| 1342 | platform_device_unregister(&m8xx_device); | 1282 | return 0; |
| 1343 | driver_unregister(&m8xx_driver); | 1283 | } |
| 1284 | |||
| 1285 | #ifdef CONFIG_PM | ||
| 1286 | static int m8xx_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 1287 | { | ||
| 1288 | return pcmcia_socket_dev_suspend(&pdev->dev, state); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | static int m8xx_resume(struct platform_device *pdev) | ||
| 1292 | { | ||
| 1293 | return pcmcia_socket_dev_resume(&pdev->dev); | ||
| 1294 | } | ||
| 1295 | #else | ||
| 1296 | #define m8xx_suspend NULL | ||
| 1297 | #define m8xx_resume NULL | ||
| 1298 | #endif | ||
| 1299 | |||
| 1300 | static struct of_device_id m8xx_pcmcia_match[] = { | ||
| 1301 | { | ||
| 1302 | .type = "pcmcia", | ||
| 1303 | .compatible = "fsl,pq-pcmcia", | ||
| 1304 | }, | ||
| 1305 | {}, | ||
| 1306 | }; | ||
| 1307 | |||
| 1308 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); | ||
| 1309 | |||
| 1310 | static struct of_platform_driver m8xx_pcmcia_driver = { | ||
| 1311 | .name = (char *) driver_name, | ||
| 1312 | .match_table = m8xx_pcmcia_match, | ||
| 1313 | .probe = m8xx_probe, | ||
| 1314 | .remove = m8xx_remove, | ||
| 1315 | .suspend = m8xx_suspend, | ||
| 1316 | .resume = m8xx_resume, | ||
| 1317 | }; | ||
| 1318 | |||
| 1319 | static int __init m8xx_init(void) | ||
| 1320 | { | ||
| 1321 | return of_register_platform_driver(&m8xx_pcmcia_driver); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static void __exit m8xx_exit(void) | ||
| 1325 | { | ||
| 1326 | of_unregister_platform_driver(&m8xx_pcmcia_driver); | ||
| 1344 | } | 1327 | } |
| 1345 | 1328 | ||
| 1346 | module_init(m8xx_init); | 1329 | module_init(m8xx_init); |
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile index e251d1c1171c..746031de2195 100644 --- a/drivers/ps3/Makefile +++ b/drivers/ps3/Makefile | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | obj-$(CONFIG_PS3_VUART) += vuart.o | 1 | obj-$(CONFIG_PS3_VUART) += vuart.o |
| 2 | obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o | 2 | obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o |
| 3 | ps3av_mod-objs += ps3av.o ps3av_cmd.o | ||
| 4 | obj-$(CONFIG_PPC_PS3) += sys-manager-core.o | ||
| 3 | obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o | 5 | obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o |
| 6 | obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o | ||
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 1393e64335f9..85e21614f868 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c | |||
| @@ -1,32 +1,30 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 2 | * PS3 AV backend support. |
| 3 | * Copyright 2006, 2007 Sony Corporation | ||
| 4 | * | 3 | * |
| 5 | * AV backend support for PS3 | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * under the terms of the GNU General Public License as published | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * by the Free Software Foundation; version 2 of the License. | 9 | * the Free Software Foundation; version 2 of the License. |
| 10 | * | 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, but | 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * General Public License for more details. | 14 | * GNU General Public License for more details. |
| 15 | * | 15 | * |
| 16 | * You should have received a copy of the GNU General Public License along | 16 | * You should have received a copy of the GNU General Public License |
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | 17 | * along with this program; if not, write to the Free Software |
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 23 | #include <linux/notifier.h> | 24 | #include <linux/notifier.h> |
| 24 | #include <linux/reboot.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/ioctl.h> | 25 | #include <linux/ioctl.h> |
| 27 | 26 | ||
| 28 | #include <asm/firmware.h> | 27 | #include <asm/firmware.h> |
| 29 | #include <asm/lv1call.h> | ||
| 30 | #include <asm/ps3av.h> | 28 | #include <asm/ps3av.h> |
| 31 | #include <asm/ps3.h> | 29 | #include <asm/ps3.h> |
| 32 | 30 | ||
| @@ -39,13 +37,12 @@ static int timeout = 5000; /* in msec ( 5 sec ) */ | |||
| 39 | module_param(timeout, int, 0644); | 37 | module_param(timeout, int, 0644); |
| 40 | 38 | ||
| 41 | static struct ps3av { | 39 | static struct ps3av { |
| 42 | int available; | ||
| 43 | struct mutex mutex; | 40 | struct mutex mutex; |
| 44 | struct work_struct work; | 41 | struct work_struct work; |
| 45 | struct completion done; | 42 | struct completion done; |
| 46 | struct workqueue_struct *wq; | 43 | struct workqueue_struct *wq; |
| 47 | int open_count; | 44 | int open_count; |
| 48 | struct ps3_vuart_port_device *dev; | 45 | struct ps3_system_bus_device *dev; |
| 49 | 46 | ||
| 50 | int region; | 47 | int region; |
| 51 | struct ps3av_pkt_av_get_hw_conf av_hw_conf; | 48 | struct ps3av_pkt_av_get_hw_conf av_hw_conf; |
| @@ -55,11 +52,13 @@ static struct ps3av { | |||
| 55 | u32 audio_port; | 52 | u32 audio_port; |
| 56 | int ps3av_mode; | 53 | int ps3av_mode; |
| 57 | int ps3av_mode_old; | 54 | int ps3av_mode_old; |
| 58 | } ps3av; | 55 | union { |
| 59 | 56 | struct ps3av_reply_hdr reply_hdr; | |
| 60 | static struct ps3_vuart_port_device ps3av_dev = { | 57 | u8 raw[PS3AV_BUF_SIZE]; |
| 61 | .match_id = PS3_MATCH_ID_AV_SETTINGS | 58 | } recv_buf; |
| 62 | }; | 59 | void (*flip_ctl)(int on, void *data); |
| 60 | void *flip_data; | ||
| 61 | } *ps3av; | ||
| 63 | 62 | ||
| 64 | /* color space */ | 63 | /* color space */ |
| 65 | #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 | 64 | #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 |
| @@ -169,7 +168,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) | |||
| 169 | if (hdr->cid & PS3AV_EVENT_CMD_MASK) { | 168 | if (hdr->cid & PS3AV_EVENT_CMD_MASK) { |
| 170 | table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); | 169 | table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); |
| 171 | if (table) | 170 | if (table) |
| 172 | dev_dbg(&ps3av_dev.core, | 171 | dev_dbg(&ps3av->dev->core, |
| 173 | "recv event packet cid:%08x port:0x%x size:%d\n", | 172 | "recv event packet cid:%08x port:0x%x size:%d\n", |
| 174 | hdr->cid, ps3av_event_get_port_id(hdr->cid), | 173 | hdr->cid, ps3av_event_get_port_id(hdr->cid), |
| 175 | hdr->size); | 174 | hdr->size); |
| @@ -182,6 +181,41 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) | |||
| 182 | return 0; | 181 | return 0; |
| 183 | } | 182 | } |
| 184 | 183 | ||
| 184 | |||
| 185 | #define POLLING_INTERVAL 25 /* in msec */ | ||
| 186 | |||
| 187 | static int ps3av_vuart_write(struct ps3_system_bus_device *dev, | ||
| 188 | const void *buf, unsigned long size) | ||
| 189 | { | ||
| 190 | int error; | ||
| 191 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | ||
| 192 | error = ps3_vuart_write(dev, buf, size); | ||
| 193 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
| 194 | return error ? error : size; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf, | ||
| 198 | unsigned long size, int timeout) | ||
| 199 | { | ||
| 200 | int error; | ||
| 201 | int loopcnt = 0; | ||
| 202 | |||
| 203 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | ||
| 204 | timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; | ||
| 205 | while (loopcnt++ <= timeout) { | ||
| 206 | error = ps3_vuart_read(dev, buf, size); | ||
| 207 | if (!error) | ||
| 208 | return size; | ||
| 209 | if (error != -EAGAIN) { | ||
| 210 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", | ||
| 211 | __func__, error); | ||
| 212 | return error; | ||
| 213 | } | ||
| 214 | msleep(POLLING_INTERVAL); | ||
| 215 | } | ||
| 216 | return -EWOULDBLOCK; | ||
| 217 | } | ||
| 218 | |||
| 185 | static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | 219 | static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, |
| 186 | struct ps3av_reply_hdr *recv_buf, int write_len, | 220 | struct ps3av_reply_hdr *recv_buf, int write_len, |
| 187 | int read_len) | 221 | int read_len) |
| @@ -190,13 +224,13 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
| 190 | u32 cmd; | 224 | u32 cmd; |
| 191 | int event; | 225 | int event; |
| 192 | 226 | ||
| 193 | if (!ps3av.available) | 227 | if (!ps3av) |
| 194 | return -ENODEV; | 228 | return -ENODEV; |
| 195 | 229 | ||
| 196 | /* send pkt */ | 230 | /* send pkt */ |
| 197 | res = ps3av_vuart_write(ps3av.dev, send_buf, write_len); | 231 | res = ps3av_vuart_write(ps3av->dev, send_buf, write_len); |
| 198 | if (res < 0) { | 232 | if (res < 0) { |
| 199 | dev_dbg(&ps3av_dev.core, | 233 | dev_dbg(&ps3av->dev->core, |
| 200 | "%s: ps3av_vuart_write() failed (result=%d)\n", | 234 | "%s: ps3av_vuart_write() failed (result=%d)\n", |
| 201 | __func__, res); | 235 | __func__, res); |
| 202 | return res; | 236 | return res; |
| @@ -206,20 +240,20 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
| 206 | cmd = send_buf->cid; | 240 | cmd = send_buf->cid; |
| 207 | do { | 241 | do { |
| 208 | /* read header */ | 242 | /* read header */ |
| 209 | res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE, | 243 | res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE, |
| 210 | timeout); | 244 | timeout); |
| 211 | if (res != PS3AV_HDR_SIZE) { | 245 | if (res != PS3AV_HDR_SIZE) { |
| 212 | dev_dbg(&ps3av_dev.core, | 246 | dev_dbg(&ps3av->dev->core, |
| 213 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 247 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
| 214 | __func__, res); | 248 | __func__, res); |
| 215 | return res; | 249 | return res; |
| 216 | } | 250 | } |
| 217 | 251 | ||
| 218 | /* read body */ | 252 | /* read body */ |
| 219 | res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid, | 253 | res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid, |
| 220 | recv_buf->size, timeout); | 254 | recv_buf->size, timeout); |
| 221 | if (res < 0) { | 255 | if (res < 0) { |
| 222 | dev_dbg(&ps3av_dev.core, | 256 | dev_dbg(&ps3av->dev->core, |
| 223 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 257 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
| 224 | __func__, res); | 258 | __func__, res); |
| 225 | return res; | 259 | return res; |
| @@ -230,7 +264,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
| 230 | } while (event); | 264 | } while (event); |
| 231 | 265 | ||
| 232 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { | 266 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { |
| 233 | dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", | 267 | dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n", |
| 234 | __func__, recv_buf->cid); | 268 | __func__, recv_buf->cid); |
| 235 | return -EINVAL; | 269 | return -EINVAL; |
| 236 | } | 270 | } |
| @@ -245,7 +279,7 @@ static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, | |||
| 245 | int return_len; | 279 | int return_len; |
| 246 | 280 | ||
| 247 | if (recv_buf->version != PS3AV_VERSION) { | 281 | if (recv_buf->version != PS3AV_VERSION) { |
| 248 | dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n", | 282 | dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n", |
| 249 | recv_buf->version); | 283 | recv_buf->version); |
| 250 | return -EFAULT; | 284 | return -EFAULT; |
| 251 | } | 285 | } |
| @@ -267,16 +301,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
| 267 | struct ps3av_send_hdr *buf) | 301 | struct ps3av_send_hdr *buf) |
| 268 | { | 302 | { |
| 269 | int res = 0; | 303 | int res = 0; |
| 270 | static union { | ||
| 271 | struct ps3av_reply_hdr reply_hdr; | ||
| 272 | u8 raw[PS3AV_BUF_SIZE]; | ||
| 273 | } recv_buf; | ||
| 274 | |||
| 275 | u32 *table; | 304 | u32 *table; |
| 276 | 305 | ||
| 277 | BUG_ON(!ps3av.available); | 306 | BUG_ON(!ps3av); |
| 278 | 307 | ||
| 279 | mutex_lock(&ps3av.mutex); | 308 | mutex_lock(&ps3av->mutex); |
| 280 | 309 | ||
| 281 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); | 310 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); |
| 282 | BUG_ON(!table); | 311 | BUG_ON(!table); |
| @@ -288,7 +317,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
| 288 | ps3av_set_hdr(cid, send_len, buf); | 317 | ps3av_set_hdr(cid, send_len, buf); |
| 289 | 318 | ||
| 290 | /* send packet via vuart */ | 319 | /* send packet via vuart */ |
| 291 | res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len, | 320 | res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len, |
| 292 | usr_buf_size); | 321 | usr_buf_size); |
| 293 | if (res < 0) { | 322 | if (res < 0) { |
| 294 | printk(KERN_ERR | 323 | printk(KERN_ERR |
| @@ -298,7 +327,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
| 298 | } | 327 | } |
| 299 | 328 | ||
| 300 | /* process reply packet */ | 329 | /* process reply packet */ |
| 301 | res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr, | 330 | res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr, |
| 302 | usr_buf_size); | 331 | usr_buf_size); |
| 303 | if (res < 0) { | 332 | if (res < 0) { |
| 304 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", | 333 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", |
| @@ -306,11 +335,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
| 306 | goto err; | 335 | goto err; |
| 307 | } | 336 | } |
| 308 | 337 | ||
| 309 | mutex_unlock(&ps3av.mutex); | 338 | mutex_unlock(&ps3av->mutex); |
| 310 | return 0; | 339 | return 0; |
| 311 | 340 | ||
| 312 | err: | 341 | err: |
| 313 | mutex_unlock(&ps3av.mutex); | 342 | mutex_unlock(&ps3av->mutex); |
| 314 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); | 343 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); |
| 315 | return res; | 344 | return res; |
| 316 | } | 345 | } |
| @@ -319,11 +348,11 @@ static int ps3av_set_av_video_mute(u32 mute) | |||
| 319 | { | 348 | { |
| 320 | int i, num_of_av_port, res; | 349 | int i, num_of_av_port, res; |
| 321 | 350 | ||
| 322 | num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + | 351 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
| 323 | ps3av.av_hw_conf.num_of_avmulti; | 352 | ps3av->av_hw_conf.num_of_avmulti; |
| 324 | /* video mute on */ | 353 | /* video mute on */ |
| 325 | for (i = 0; i < num_of_av_port; i++) { | 354 | for (i = 0; i < num_of_av_port; i++) { |
| 326 | res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute); | 355 | res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute); |
| 327 | if (res < 0) | 356 | if (res < 0) |
| 328 | return -1; | 357 | return -1; |
| 329 | } | 358 | } |
| @@ -335,13 +364,13 @@ static int ps3av_set_video_disable_sig(void) | |||
| 335 | { | 364 | { |
| 336 | int i, num_of_hdmi_port, num_of_av_port, res; | 365 | int i, num_of_hdmi_port, num_of_av_port, res; |
| 337 | 366 | ||
| 338 | num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi; | 367 | num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi; |
| 339 | num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + | 368 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
| 340 | ps3av.av_hw_conf.num_of_avmulti; | 369 | ps3av->av_hw_conf.num_of_avmulti; |
| 341 | 370 | ||
| 342 | /* tv mute */ | 371 | /* tv mute */ |
| 343 | for (i = 0; i < num_of_hdmi_port; i++) { | 372 | for (i = 0; i < num_of_hdmi_port; i++) { |
| 344 | res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], | 373 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], |
| 345 | PS3AV_CMD_MUTE_ON); | 374 | PS3AV_CMD_MUTE_ON); |
| 346 | if (res < 0) | 375 | if (res < 0) |
| 347 | return -1; | 376 | return -1; |
| @@ -350,11 +379,11 @@ static int ps3av_set_video_disable_sig(void) | |||
| 350 | 379 | ||
| 351 | /* video mute on */ | 380 | /* video mute on */ |
| 352 | for (i = 0; i < num_of_av_port; i++) { | 381 | for (i = 0; i < num_of_av_port; i++) { |
| 353 | res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]); | 382 | res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]); |
| 354 | if (res < 0) | 383 | if (res < 0) |
| 355 | return -1; | 384 | return -1; |
| 356 | if (i < num_of_hdmi_port) { | 385 | if (i < num_of_hdmi_port) { |
| 357 | res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], | 386 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], |
| 358 | PS3AV_CMD_MUTE_OFF); | 387 | PS3AV_CMD_MUTE_OFF); |
| 359 | if (res < 0) | 388 | if (res < 0) |
| 360 | return -1; | 389 | return -1; |
| @@ -369,17 +398,17 @@ static int ps3av_set_audio_mute(u32 mute) | |||
| 369 | { | 398 | { |
| 370 | int i, num_of_av_port, num_of_opt_port, res; | 399 | int i, num_of_av_port, num_of_opt_port, res; |
| 371 | 400 | ||
| 372 | num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + | 401 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
| 373 | ps3av.av_hw_conf.num_of_avmulti; | 402 | ps3av->av_hw_conf.num_of_avmulti; |
| 374 | num_of_opt_port = ps3av.av_hw_conf.num_of_spdif; | 403 | num_of_opt_port = ps3av->av_hw_conf.num_of_spdif; |
| 375 | 404 | ||
| 376 | for (i = 0; i < num_of_av_port; i++) { | 405 | for (i = 0; i < num_of_av_port; i++) { |
| 377 | res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute); | 406 | res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute); |
| 378 | if (res < 0) | 407 | if (res < 0) |
| 379 | return -1; | 408 | return -1; |
| 380 | } | 409 | } |
| 381 | for (i = 0; i < num_of_opt_port; i++) { | 410 | for (i = 0; i < num_of_opt_port; i++) { |
| 382 | res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute); | 411 | res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute); |
| 383 | if (res < 0) | 412 | if (res < 0) |
| 384 | return -1; | 413 | return -1; |
| 385 | } | 414 | } |
| @@ -394,40 +423,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) | |||
| 394 | struct ps3av_pkt_audio_mode audio_mode; | 423 | struct ps3av_pkt_audio_mode audio_mode; |
| 395 | u32 len = 0; | 424 | u32 len = 0; |
| 396 | 425 | ||
| 397 | num_of_audio = ps3av.av_hw_conf.num_of_hdmi + | 426 | num_of_audio = ps3av->av_hw_conf.num_of_hdmi + |
| 398 | ps3av.av_hw_conf.num_of_avmulti + | 427 | ps3av->av_hw_conf.num_of_avmulti + |
| 399 | ps3av.av_hw_conf.num_of_spdif; | 428 | ps3av->av_hw_conf.num_of_spdif; |
| 400 | 429 | ||
| 401 | avb_param.num_of_video_pkt = 0; | 430 | avb_param.num_of_video_pkt = 0; |
| 402 | avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ | 431 | avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ |
| 403 | avb_param.num_of_av_video_pkt = 0; | 432 | avb_param.num_of_av_video_pkt = 0; |
| 404 | avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi; | 433 | avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi; |
| 405 | 434 | ||
| 406 | vid = video_mode_table[ps3av.ps3av_mode].vid; | 435 | vid = video_mode_table[ps3av->ps3av_mode].vid; |
| 407 | 436 | ||
| 408 | /* audio mute */ | 437 | /* audio mute */ |
| 409 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); | 438 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); |
| 410 | 439 | ||
| 411 | /* audio inactive */ | 440 | /* audio inactive */ |
| 412 | res = ps3av_cmd_audio_active(0, ps3av.audio_port); | 441 | res = ps3av_cmd_audio_active(0, ps3av->audio_port); |
| 413 | if (res < 0) | 442 | if (res < 0) |
| 414 | dev_dbg(&ps3av_dev.core, | 443 | dev_dbg(&ps3av->dev->core, |
| 415 | "ps3av_cmd_audio_active OFF failed\n"); | 444 | "ps3av_cmd_audio_active OFF failed\n"); |
| 416 | 445 | ||
| 417 | /* audio_pkt */ | 446 | /* audio_pkt */ |
| 418 | for (i = 0; i < num_of_audio; i++) { | 447 | for (i = 0; i < num_of_audio; i++) { |
| 419 | ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs, | 448 | ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch, |
| 420 | word_bits, format, source); | 449 | fs, word_bits, format, source); |
| 421 | if (i < ps3av.av_hw_conf.num_of_hdmi) { | 450 | if (i < ps3av->av_hw_conf.num_of_hdmi) { |
| 422 | /* hdmi only */ | 451 | /* hdmi only */ |
| 423 | len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], | 452 | len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], |
| 424 | ps3av.av_port[i], | 453 | ps3av->av_port[i], |
| 425 | &audio_mode, vid); | 454 | &audio_mode, vid); |
| 426 | } | 455 | } |
| 427 | /* audio_mode pkt should be sent separately */ | 456 | /* audio_mode pkt should be sent separately */ |
| 428 | res = ps3av_cmd_audio_mode(&audio_mode); | 457 | res = ps3av_cmd_audio_mode(&audio_mode); |
| 429 | if (res < 0) | 458 | if (res < 0) |
| 430 | dev_dbg(&ps3av_dev.core, | 459 | dev_dbg(&ps3av->dev->core, |
| 431 | "ps3av_cmd_audio_mode failed, port:%x\n", i); | 460 | "ps3av_cmd_audio_mode failed, port:%x\n", i); |
| 432 | } | 461 | } |
| 433 | 462 | ||
| @@ -435,15 +464,16 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) | |||
| 435 | len += offsetof(struct ps3av_pkt_avb_param, buf); | 464 | len += offsetof(struct ps3av_pkt_avb_param, buf); |
| 436 | res = ps3av_cmd_avb_param(&avb_param, len); | 465 | res = ps3av_cmd_avb_param(&avb_param, len); |
| 437 | if (res < 0) | 466 | if (res < 0) |
| 438 | dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); | 467 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); |
| 439 | 468 | ||
| 440 | /* audio mute */ | 469 | /* audio mute */ |
| 441 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); | 470 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); |
| 442 | 471 | ||
| 443 | /* audio active */ | 472 | /* audio active */ |
| 444 | res = ps3av_cmd_audio_active(1, ps3av.audio_port); | 473 | res = ps3av_cmd_audio_active(1, ps3av->audio_port); |
| 445 | if (res < 0) | 474 | if (res < 0) |
| 446 | dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n"); | 475 | dev_dbg(&ps3av->dev->core, |
| 476 | "ps3av_cmd_audio_active ON failed\n"); | ||
| 447 | 477 | ||
| 448 | return 0; | 478 | return 0; |
| 449 | } | 479 | } |
| @@ -456,7 +486,7 @@ static int ps3av_set_videomode(void) | |||
| 456 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); | 486 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); |
| 457 | 487 | ||
| 458 | /* wake up ps3avd to do the actual video mode setting */ | 488 | /* wake up ps3avd to do the actual video mode setting */ |
| 459 | queue_work(ps3av.wq, &ps3av.work); | 489 | queue_work(ps3av->wq, &ps3av->work); |
| 460 | 490 | ||
| 461 | return 0; | 491 | return 0; |
| 462 | } | 492 | } |
| @@ -473,8 +503,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
| 473 | 503 | ||
| 474 | avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ | 504 | avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ |
| 475 | avb_param.num_of_audio_pkt = 0; | 505 | avb_param.num_of_audio_pkt = 0; |
| 476 | avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi + | 506 | avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + |
| 477 | ps3av.av_hw_conf.num_of_avmulti; | 507 | ps3av->av_hw_conf.num_of_avmulti; |
| 478 | avb_param.num_of_av_audio_pkt = 0; | 508 | avb_param.num_of_av_audio_pkt = 0; |
| 479 | 509 | ||
| 480 | /* video signal off */ | 510 | /* video signal off */ |
| @@ -484,21 +514,21 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
| 484 | if (id & PS3AV_MODE_HDCP_OFF) { | 514 | if (id & PS3AV_MODE_HDCP_OFF) { |
| 485 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); | 515 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); |
| 486 | if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) | 516 | if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) |
| 487 | dev_dbg(&ps3av_dev.core, "Not supported\n"); | 517 | dev_dbg(&ps3av->dev->core, "Not supported\n"); |
| 488 | else if (res) | 518 | else if (res) |
| 489 | dev_dbg(&ps3av_dev.core, | 519 | dev_dbg(&ps3av->dev->core, |
| 490 | "ps3av_cmd_av_hdmi_mode failed\n"); | 520 | "ps3av_cmd_av_hdmi_mode failed\n"); |
| 491 | } else if (old_id & PS3AV_MODE_HDCP_OFF) { | 521 | } else if (old_id & PS3AV_MODE_HDCP_OFF) { |
| 492 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); | 522 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); |
| 493 | if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) | 523 | if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) |
| 494 | dev_dbg(&ps3av_dev.core, | 524 | dev_dbg(&ps3av->dev->core, |
| 495 | "ps3av_cmd_av_hdmi_mode failed\n"); | 525 | "ps3av_cmd_av_hdmi_mode failed\n"); |
| 496 | } | 526 | } |
| 497 | 527 | ||
| 498 | /* video_pkt */ | 528 | /* video_pkt */ |
| 499 | for (i = 0; i < avb_param.num_of_video_pkt; i++) | 529 | for (i = 0; i < avb_param.num_of_video_pkt; i++) |
| 500 | len += ps3av_cmd_set_video_mode(&avb_param.buf[len], | 530 | len += ps3av_cmd_set_video_mode(&avb_param.buf[len], |
| 501 | ps3av.head[i], video_mode->vid, | 531 | ps3av->head[i], video_mode->vid, |
| 502 | video_mode->fmt, id); | 532 | video_mode->fmt, id); |
| 503 | /* av_video_pkt */ | 533 | /* av_video_pkt */ |
| 504 | for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { | 534 | for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { |
| @@ -507,12 +537,12 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
| 507 | else | 537 | else |
| 508 | av_video_cs = video_mode->cs; | 538 | av_video_cs = video_mode->cs; |
| 509 | #ifndef PS3AV_HDMI_YUV | 539 | #ifndef PS3AV_HDMI_YUV |
| 510 | if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || | 540 | if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || |
| 511 | ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) | 541 | ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) |
| 512 | av_video_cs = RGB8; /* use RGB for HDMI */ | 542 | av_video_cs = RGB8; /* use RGB for HDMI */ |
| 513 | #endif | 543 | #endif |
| 514 | len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], | 544 | len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], |
| 515 | ps3av.av_port[i], | 545 | ps3av->av_port[i], |
| 516 | video_mode->vid, av_video_cs, | 546 | video_mode->vid, av_video_cs, |
| 517 | video_mode->aspect, id); | 547 | video_mode->aspect, id); |
| 518 | } | 548 | } |
| @@ -524,7 +554,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
| 524 | "%s: Command failed. Please try your request again. \n", | 554 | "%s: Command failed. Please try your request again. \n", |
| 525 | __func__); | 555 | __func__); |
| 526 | else if (res) | 556 | else if (res) |
| 527 | dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); | 557 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); |
| 528 | 558 | ||
| 529 | msleep(1500); | 559 | msleep(1500); |
| 530 | /* av video mute */ | 560 | /* av video mute */ |
| @@ -533,8 +563,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
| 533 | 563 | ||
| 534 | static void ps3avd(struct work_struct *work) | 564 | static void ps3avd(struct work_struct *work) |
| 535 | { | 565 | { |
| 536 | ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old); | 566 | ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old); |
| 537 | complete(&ps3av.done); | 567 | complete(&ps3av->done); |
| 538 | } | 568 | } |
| 539 | 569 | ||
| 540 | static int ps3av_vid2table_id(int vid) | 570 | static int ps3av_vid2table_id(int vid) |
| @@ -601,7 +631,7 @@ static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info) | |||
| 601 | return vid; | 631 | return vid; |
| 602 | } | 632 | } |
| 603 | 633 | ||
| 604 | if (ps3av.region & PS3AV_REGION_60) | 634 | if (ps3av->region & PS3AV_REGION_60) |
| 605 | vid = PS3AV_DEFAULT_HDMI_VID_REG_60; | 635 | vid = PS3AV_DEFAULT_HDMI_VID_REG_60; |
| 606 | else | 636 | else |
| 607 | vid = PS3AV_DEFAULT_HDMI_VID_REG_50; | 637 | vid = PS3AV_DEFAULT_HDMI_VID_REG_50; |
| @@ -643,16 +673,16 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf, | |||
| 643 | vid = PS3AV_DEFAULT_DVI_VID; | 673 | vid = PS3AV_DEFAULT_DVI_VID; |
| 644 | } else if (vid == -1) { | 674 | } else if (vid == -1) { |
| 645 | /* no HDMI interface or HDMI is off */ | 675 | /* no HDMI interface or HDMI is off */ |
| 646 | if (ps3av.region & PS3AV_REGION_60) | 676 | if (ps3av->region & PS3AV_REGION_60) |
| 647 | vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; | 677 | vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; |
| 648 | else | 678 | else |
| 649 | vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; | 679 | vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; |
| 650 | if (ps3av.region & PS3AV_REGION_RGB) | 680 | if (ps3av->region & PS3AV_REGION_RGB) |
| 651 | rgb = PS3AV_MODE_RGB; | 681 | rgb = PS3AV_MODE_RGB; |
| 652 | } else if (boot) { | 682 | } else if (boot) { |
| 653 | /* HDMI: using DEFAULT HDMI_VID while booting up */ | 683 | /* HDMI: using DEFAULT HDMI_VID while booting up */ |
| 654 | info = &monitor_info.info; | 684 | info = &monitor_info.info; |
| 655 | if (ps3av.region & PS3AV_REGION_60) { | 685 | if (ps3av->region & PS3AV_REGION_60) { |
| 656 | if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) | 686 | if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) |
| 657 | vid = PS3AV_DEFAULT_HDMI_VID_REG_60; | 687 | vid = PS3AV_DEFAULT_HDMI_VID_REG_60; |
| 658 | else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) | 688 | else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) |
| @@ -715,14 +745,14 @@ int ps3av_set_video_mode(u32 id, int boot) | |||
| 715 | 745 | ||
| 716 | size = ARRAY_SIZE(video_mode_table); | 746 | size = ARRAY_SIZE(video_mode_table); |
| 717 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { | 747 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { |
| 718 | dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id); | 748 | dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id); |
| 719 | return -EINVAL; | 749 | return -EINVAL; |
| 720 | } | 750 | } |
| 721 | 751 | ||
| 722 | /* auto mode */ | 752 | /* auto mode */ |
| 723 | option = id & ~PS3AV_MODE_MASK; | 753 | option = id & ~PS3AV_MODE_MASK; |
| 724 | if ((id & PS3AV_MODE_MASK) == 0) { | 754 | if ((id & PS3AV_MODE_MASK) == 0) { |
| 725 | id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); | 755 | id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot); |
| 726 | if (id < 1) { | 756 | if (id < 1) { |
| 727 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); | 757 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
| 728 | return -EINVAL; | 758 | return -EINVAL; |
| @@ -731,11 +761,11 @@ int ps3av_set_video_mode(u32 id, int boot) | |||
| 731 | } | 761 | } |
| 732 | 762 | ||
| 733 | /* set videomode */ | 763 | /* set videomode */ |
| 734 | wait_for_completion(&ps3av.done); | 764 | wait_for_completion(&ps3av->done); |
| 735 | ps3av.ps3av_mode_old = ps3av.ps3av_mode; | 765 | ps3av->ps3av_mode_old = ps3av->ps3av_mode; |
| 736 | ps3av.ps3av_mode = id; | 766 | ps3av->ps3av_mode = id; |
| 737 | if (ps3av_set_videomode()) | 767 | if (ps3av_set_videomode()) |
| 738 | ps3av.ps3av_mode = ps3av.ps3av_mode_old; | 768 | ps3av->ps3av_mode = ps3av->ps3av_mode_old; |
| 739 | 769 | ||
| 740 | return 0; | 770 | return 0; |
| 741 | } | 771 | } |
| @@ -744,7 +774,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode); | |||
| 744 | 774 | ||
| 745 | int ps3av_get_auto_mode(int boot) | 775 | int ps3av_get_auto_mode(int boot) |
| 746 | { | 776 | { |
| 747 | return ps3av_auto_videomode(&ps3av.av_hw_conf, boot); | 777 | return ps3av_auto_videomode(&ps3av->av_hw_conf, boot); |
| 748 | } | 778 | } |
| 749 | 779 | ||
| 750 | EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); | 780 | EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); |
| @@ -772,7 +802,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode); | |||
| 772 | 802 | ||
| 773 | int ps3av_get_mode(void) | 803 | int ps3av_get_mode(void) |
| 774 | { | 804 | { |
| 775 | return ps3av.ps3av_mode; | 805 | return ps3av ? ps3av->ps3av_mode : 0; |
| 776 | } | 806 | } |
| 777 | 807 | ||
| 778 | EXPORT_SYMBOL_GPL(ps3av_get_mode); | 808 | EXPORT_SYMBOL_GPL(ps3av_get_mode); |
| @@ -842,82 +872,65 @@ int ps3av_audio_mute(int mute) | |||
| 842 | 872 | ||
| 843 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); | 873 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); |
| 844 | 874 | ||
| 845 | int ps3av_dev_open(void) | 875 | void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), |
| 876 | void *flip_data) | ||
| 846 | { | 877 | { |
| 847 | int status = 0; | 878 | mutex_lock(&ps3av->mutex); |
| 848 | 879 | ps3av->flip_ctl = flip_ctl; | |
| 849 | mutex_lock(&ps3av.mutex); | 880 | ps3av->flip_data = flip_data; |
| 850 | if (!ps3av.open_count++) { | 881 | mutex_unlock(&ps3av->mutex); |
| 851 | status = lv1_gpu_open(0); | ||
| 852 | if (status) { | ||
| 853 | printk(KERN_ERR "%s: lv1_gpu_open failed %d\n", | ||
| 854 | __func__, status); | ||
| 855 | ps3av.open_count--; | ||
| 856 | } | ||
| 857 | } | ||
| 858 | mutex_unlock(&ps3av.mutex); | ||
| 859 | |||
| 860 | return status; | ||
| 861 | } | 882 | } |
| 883 | EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); | ||
| 862 | 884 | ||
| 863 | EXPORT_SYMBOL_GPL(ps3av_dev_open); | 885 | void ps3av_flip_ctl(int on) |
| 864 | |||
| 865 | int ps3av_dev_close(void) | ||
| 866 | { | 886 | { |
| 867 | int status = 0; | 887 | mutex_lock(&ps3av->mutex); |
| 868 | 888 | if (ps3av->flip_ctl) | |
| 869 | mutex_lock(&ps3av.mutex); | 889 | ps3av->flip_ctl(on, ps3av->flip_data); |
| 870 | if (ps3av.open_count <= 0) { | 890 | mutex_unlock(&ps3av->mutex); |
| 871 | printk(KERN_ERR "%s: GPU already closed\n", __func__); | ||
| 872 | status = -1; | ||
| 873 | } else if (!--ps3av.open_count) { | ||
| 874 | status = lv1_gpu_close(); | ||
| 875 | if (status) | ||
| 876 | printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n", | ||
| 877 | __func__, status); | ||
| 878 | } | ||
| 879 | mutex_unlock(&ps3av.mutex); | ||
| 880 | |||
| 881 | return status; | ||
| 882 | } | 891 | } |
| 883 | 892 | ||
| 884 | EXPORT_SYMBOL_GPL(ps3av_dev_close); | 893 | static int ps3av_probe(struct ps3_system_bus_device *dev) |
| 885 | |||
| 886 | static int ps3av_probe(struct ps3_vuart_port_device *dev) | ||
| 887 | { | 894 | { |
| 888 | int res; | 895 | int res; |
| 889 | u32 id; | 896 | u32 id; |
| 890 | 897 | ||
| 891 | dev_dbg(&ps3av_dev.core, "init ...\n"); | 898 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
| 892 | dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout); | 899 | dev_dbg(&dev->core, " timeout=%d\n", timeout); |
| 893 | 900 | ||
| 894 | memset(&ps3av, 0, sizeof(ps3av)); | 901 | if (ps3av) { |
| 895 | 902 | dev_err(&dev->core, "Only one ps3av device is supported\n"); | |
| 896 | mutex_init(&ps3av.mutex); | 903 | return -EBUSY; |
| 897 | ps3av.ps3av_mode = 0; | 904 | } |
| 898 | ps3av.dev = dev; | ||
| 899 | 905 | ||
| 900 | INIT_WORK(&ps3av.work, ps3avd); | 906 | ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL); |
| 901 | init_completion(&ps3av.done); | 907 | if (!ps3av) |
| 902 | complete(&ps3av.done); | ||
| 903 | ps3av.wq = create_singlethread_workqueue("ps3avd"); | ||
| 904 | if (!ps3av.wq) | ||
| 905 | return -ENOMEM; | 908 | return -ENOMEM; |
| 906 | 909 | ||
| 907 | ps3av.available = 1; | 910 | mutex_init(&ps3av->mutex); |
| 911 | ps3av->ps3av_mode = 0; | ||
| 912 | ps3av->dev = dev; | ||
| 913 | |||
| 914 | INIT_WORK(&ps3av->work, ps3avd); | ||
| 915 | init_completion(&ps3av->done); | ||
| 916 | complete(&ps3av->done); | ||
| 917 | ps3av->wq = create_singlethread_workqueue("ps3avd"); | ||
| 918 | if (!ps3av->wq) | ||
| 919 | goto fail; | ||
| 920 | |||
| 908 | switch (ps3_os_area_get_av_multi_out()) { | 921 | switch (ps3_os_area_get_av_multi_out()) { |
| 909 | case PS3_PARAM_AV_MULTI_OUT_NTSC: | 922 | case PS3_PARAM_AV_MULTI_OUT_NTSC: |
| 910 | ps3av.region = PS3AV_REGION_60; | 923 | ps3av->region = PS3AV_REGION_60; |
| 911 | break; | 924 | break; |
| 912 | case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: | 925 | case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: |
| 913 | case PS3_PARAM_AV_MULTI_OUT_SECAM: | 926 | case PS3_PARAM_AV_MULTI_OUT_SECAM: |
| 914 | ps3av.region = PS3AV_REGION_50; | 927 | ps3av->region = PS3AV_REGION_50; |
| 915 | break; | 928 | break; |
| 916 | case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: | 929 | case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: |
| 917 | ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB; | 930 | ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB; |
| 918 | break; | 931 | break; |
| 919 | default: | 932 | default: |
| 920 | ps3av.region = PS3AV_REGION_60; | 933 | ps3av->region = PS3AV_REGION_60; |
| 921 | break; | 934 | break; |
| 922 | } | 935 | } |
| 923 | 936 | ||
| @@ -927,39 +940,47 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev) | |||
| 927 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, | 940 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, |
| 928 | res); | 941 | res); |
| 929 | 942 | ||
| 930 | ps3av_get_hw_conf(&ps3av); | 943 | ps3av_get_hw_conf(ps3av); |
| 931 | id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1); | 944 | id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1); |
| 932 | mutex_lock(&ps3av.mutex); | 945 | mutex_lock(&ps3av->mutex); |
| 933 | ps3av.ps3av_mode = id; | 946 | ps3av->ps3av_mode = id; |
| 934 | mutex_unlock(&ps3av.mutex); | 947 | mutex_unlock(&ps3av->mutex); |
| 935 | 948 | ||
| 936 | dev_dbg(&ps3av_dev.core, "init...done\n"); | 949 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
| 937 | 950 | ||
| 938 | return 0; | 951 | return 0; |
| 952 | |||
| 953 | fail: | ||
| 954 | kfree(ps3av); | ||
| 955 | ps3av = NULL; | ||
| 956 | return -ENOMEM; | ||
| 939 | } | 957 | } |
| 940 | 958 | ||
| 941 | static int ps3av_remove(struct ps3_vuart_port_device *dev) | 959 | static int ps3av_remove(struct ps3_system_bus_device *dev) |
| 942 | { | 960 | { |
| 943 | if (ps3av.available) { | 961 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
| 962 | if (ps3av) { | ||
| 944 | ps3av_cmd_fin(); | 963 | ps3av_cmd_fin(); |
| 945 | if (ps3av.wq) | 964 | if (ps3av->wq) |
| 946 | destroy_workqueue(ps3av.wq); | 965 | destroy_workqueue(ps3av->wq); |
| 947 | ps3av.available = 0; | 966 | kfree(ps3av); |
| 967 | ps3av = NULL; | ||
| 948 | } | 968 | } |
| 949 | 969 | ||
| 970 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
| 950 | return 0; | 971 | return 0; |
| 951 | } | 972 | } |
| 952 | 973 | ||
| 953 | static void ps3av_shutdown(struct ps3_vuart_port_device *dev) | 974 | static void ps3av_shutdown(struct ps3_system_bus_device *dev) |
| 954 | { | 975 | { |
| 976 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | ||
| 955 | ps3av_remove(dev); | 977 | ps3av_remove(dev); |
| 978 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
| 956 | } | 979 | } |
| 957 | 980 | ||
| 958 | static struct ps3_vuart_port_driver ps3av_driver = { | 981 | static struct ps3_vuart_port_driver ps3av_driver = { |
| 959 | .match_id = PS3_MATCH_ID_AV_SETTINGS, | 982 | .core.match_id = PS3_MATCH_ID_AV_SETTINGS, |
| 960 | .core = { | 983 | .core.core.name = "ps3_av", |
| 961 | .name = "ps3_av", | ||
| 962 | }, | ||
| 963 | .probe = ps3av_probe, | 984 | .probe = ps3av_probe, |
| 964 | .remove = ps3av_remove, | 985 | .remove = ps3av_remove, |
| 965 | .shutdown = ps3av_shutdown, | 986 | .shutdown = ps3av_shutdown, |
| @@ -972,6 +993,8 @@ static int ps3av_module_init(void) | |||
| 972 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | 993 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) |
| 973 | return -ENODEV; | 994 | return -ENODEV; |
| 974 | 995 | ||
| 996 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 997 | |||
| 975 | error = ps3_vuart_port_driver_register(&ps3av_driver); | 998 | error = ps3_vuart_port_driver_register(&ps3av_driver); |
| 976 | if (error) { | 999 | if (error) { |
| 977 | printk(KERN_ERR | 1000 | printk(KERN_ERR |
| @@ -980,20 +1003,21 @@ static int ps3av_module_init(void) | |||
| 980 | return error; | 1003 | return error; |
| 981 | } | 1004 | } |
| 982 | 1005 | ||
| 983 | error = ps3_vuart_port_device_register(&ps3av_dev); | 1006 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
| 984 | if (error) | ||
| 985 | printk(KERN_ERR | ||
| 986 | "%s: ps3_vuart_port_device_register failed %d\n", | ||
| 987 | __func__, error); | ||
| 988 | |||
| 989 | return error; | 1007 | return error; |
| 990 | } | 1008 | } |
| 991 | 1009 | ||
| 992 | static void __exit ps3av_module_exit(void) | 1010 | static void __exit ps3av_module_exit(void) |
| 993 | { | 1011 | { |
| 994 | device_unregister(&ps3av_dev.core); | 1012 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
| 995 | ps3_vuart_port_driver_unregister(&ps3av_driver); | 1013 | ps3_vuart_port_driver_unregister(&ps3av_driver); |
| 1014 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 996 | } | 1015 | } |
| 997 | 1016 | ||
| 998 | subsys_initcall(ps3av_module_init); | 1017 | subsys_initcall(ps3av_module_init); |
| 999 | module_exit(ps3av_module_exit); | 1018 | module_exit(ps3av_module_exit); |
| 1019 | |||
| 1020 | MODULE_LICENSE("GPL v2"); | ||
| 1021 | MODULE_DESCRIPTION("PS3 AV Settings Driver"); | ||
| 1022 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); | ||
| 1023 | MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS); | ||
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c index 0145ea173c42..f72f5ddf18e4 100644 --- a/drivers/ps3/ps3av_cmd.c +++ b/drivers/ps3/ps3av_cmd.c | |||
| @@ -143,6 +143,14 @@ static u32 ps3av_vid_video2av(int vid) | |||
| 143 | return PS3AV_CMD_AV_VID_480P; | 143 | return PS3AV_CMD_AV_VID_480P; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | static int ps3av_hdmi_range(void) | ||
| 147 | { | ||
| 148 | if (ps3_compare_firmware_version(1, 8, 0) < 0) | ||
| 149 | return 0; | ||
| 150 | else | ||
| 151 | return 1; /* supported */ | ||
| 152 | } | ||
| 153 | |||
| 146 | int ps3av_cmd_init(void) | 154 | int ps3av_cmd_init(void) |
| 147 | { | 155 | { |
| 148 | int res; | 156 | int res; |
| @@ -350,6 +358,10 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out, | |||
| 350 | /* should be same as video_mode.video_cs_out */ | 358 | /* should be same as video_mode.video_cs_out */ |
| 351 | av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); | 359 | av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); |
| 352 | av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); | 360 | av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); |
| 361 | if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range()) | ||
| 362 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON; | ||
| 363 | else /* default off */ | ||
| 364 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF; | ||
| 353 | av_video_cs->aspect = aspect; | 365 | av_video_cs->aspect = aspect; |
| 354 | if (id & PS3AV_MODE_DITHER) { | 366 | if (id & PS3AV_MODE_DITHER) { |
| 355 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON | 367 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON |
| @@ -392,6 +404,10 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt, | |||
| 392 | video_mode->pitch = video_mode->width * 4; /* line_length */ | 404 | video_mode->pitch = video_mode->width * 4; /* line_length */ |
| 393 | video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; | 405 | video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; |
| 394 | video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; | 406 | video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; |
| 407 | if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range()) | ||
| 408 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT; | ||
| 409 | else /* default enable */ | ||
| 410 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT; | ||
| 395 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; | 411 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; |
| 396 | 412 | ||
| 397 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", | 413 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", |
| @@ -852,7 +868,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | |||
| 852 | { | 868 | { |
| 853 | int res; | 869 | int res; |
| 854 | 870 | ||
| 855 | ps3fb_flip_ctl(0); /* flip off */ | 871 | ps3av_flip_ctl(0); /* flip off */ |
| 856 | 872 | ||
| 857 | /* avb packet */ | 873 | /* avb packet */ |
| 858 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), | 874 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), |
| @@ -866,7 +882,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | |||
| 866 | res); | 882 | res); |
| 867 | 883 | ||
| 868 | out: | 884 | out: |
| 869 | ps3fb_flip_ctl(1); /* flip on */ | 885 | ps3av_flip_ctl(1); /* flip on */ |
| 870 | return res; | 886 | return res; |
| 871 | } | 887 | } |
| 872 | 888 | ||
| @@ -987,34 +1003,3 @@ void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info * | |||
| 987 | | PS3AV_CMD_AV_LAYOUT_176 \ | 1003 | | PS3AV_CMD_AV_LAYOUT_176 \ |
| 988 | | PS3AV_CMD_AV_LAYOUT_192) | 1004 | | PS3AV_CMD_AV_LAYOUT_192) |
| 989 | 1005 | ||
| 990 | /************************* vuart ***************************/ | ||
| 991 | |||
| 992 | #define POLLING_INTERVAL 25 /* in msec */ | ||
| 993 | |||
| 994 | int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf, | ||
| 995 | unsigned long size) | ||
| 996 | { | ||
| 997 | int error = ps3_vuart_write(dev, buf, size); | ||
| 998 | return error ? error : size; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf, | ||
| 1002 | unsigned long size, int timeout) | ||
| 1003 | { | ||
| 1004 | int error; | ||
| 1005 | int loopcnt = 0; | ||
| 1006 | |||
| 1007 | timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; | ||
| 1008 | while (loopcnt++ <= timeout) { | ||
| 1009 | error = ps3_vuart_read(dev, buf, size); | ||
| 1010 | if (!error) | ||
| 1011 | return size; | ||
| 1012 | if (error != -EAGAIN) { | ||
| 1013 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", | ||
| 1014 | __func__, error); | ||
| 1015 | return error; | ||
| 1016 | } | ||
| 1017 | msleep(POLLING_INTERVAL); | ||
| 1018 | } | ||
| 1019 | return -EWOULDBLOCK; | ||
| 1020 | } | ||
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c new file mode 100644 index 000000000000..3a9824e3b251 --- /dev/null +++ b/drivers/ps3/ps3stor_lib.c | |||
| @@ -0,0 +1,302 @@ | |||
| 1 | /* | ||
| 2 | * PS3 Storage Library | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published | ||
| 9 | * by the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/dma-mapping.h> | ||
| 22 | |||
| 23 | #include <asm/lv1call.h> | ||
| 24 | #include <asm/ps3stor.h> | ||
| 25 | |||
| 26 | |||
| 27 | static int ps3stor_probe_access(struct ps3_storage_device *dev) | ||
| 28 | { | ||
| 29 | int res, error; | ||
| 30 | unsigned int i; | ||
| 31 | unsigned long n; | ||
| 32 | |||
| 33 | if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) { | ||
| 34 | /* special case: CD-ROM is assumed always accessible */ | ||
| 35 | dev->accessible_regions = 1; | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | error = -EPERM; | ||
| 40 | for (i = 0; i < dev->num_regions; i++) { | ||
| 41 | dev_dbg(&dev->sbd.core, | ||
| 42 | "%s:%u: checking accessibility of region %u\n", | ||
| 43 | __func__, __LINE__, i); | ||
| 44 | |||
| 45 | dev->region_idx = i; | ||
| 46 | res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1, | ||
| 47 | 0); | ||
| 48 | if (res) { | ||
| 49 | dev_dbg(&dev->sbd.core, "%s:%u: read failed, " | ||
| 50 | "region %u is not accessible\n", __func__, | ||
| 51 | __LINE__, i); | ||
| 52 | continue; | ||
| 53 | } | ||
| 54 | |||
| 55 | dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n", | ||
| 56 | __func__, __LINE__, i); | ||
| 57 | set_bit(i, &dev->accessible_regions); | ||
| 58 | |||
| 59 | /* We can access at least one region */ | ||
| 60 | error = 0; | ||
| 61 | } | ||
| 62 | if (error) | ||
| 63 | return error; | ||
| 64 | |||
| 65 | n = hweight_long(dev->accessible_regions); | ||
| 66 | if (n > 1) | ||
| 67 | dev_info(&dev->sbd.core, | ||
| 68 | "%s:%u: %lu accessible regions found. Only the first " | ||
| 69 | "one will be used", | ||
| 70 | __func__, __LINE__, n); | ||
| 71 | dev->region_idx = __ffs(dev->accessible_regions); | ||
| 72 | dev_info(&dev->sbd.core, | ||
| 73 | "First accessible region has index %u start %lu size %lu\n", | ||
| 74 | dev->region_idx, dev->regions[dev->region_idx].start, | ||
| 75 | dev->regions[dev->region_idx].size); | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | /** | ||
| 82 | * ps3stor_setup - Setup a storage device before use | ||
| 83 | * @dev: Pointer to a struct ps3_storage_device | ||
| 84 | * @handler: Pointer to an interrupt handler | ||
| 85 | * | ||
| 86 | * Returns 0 for success, or an error code | ||
| 87 | */ | ||
| 88 | int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler) | ||
| 89 | { | ||
| 90 | int error, res, alignment; | ||
| 91 | enum ps3_dma_page_size page_size; | ||
| 92 | |||
| 93 | error = ps3_open_hv_device(&dev->sbd); | ||
| 94 | if (error) { | ||
| 95 | dev_err(&dev->sbd.core, | ||
| 96 | "%s:%u: ps3_open_hv_device failed %d\n", __func__, | ||
| 97 | __LINE__, error); | ||
| 98 | goto fail; | ||
| 99 | } | ||
| 100 | |||
| 101 | error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY, | ||
| 102 | &dev->irq); | ||
| 103 | if (error) { | ||
| 104 | dev_err(&dev->sbd.core, | ||
| 105 | "%s:%u: ps3_sb_event_receive_port_setup failed %d\n", | ||
| 106 | __func__, __LINE__, error); | ||
| 107 | goto fail_close_device; | ||
| 108 | } | ||
| 109 | |||
| 110 | error = request_irq(dev->irq, handler, IRQF_DISABLED, | ||
| 111 | dev->sbd.core.driver->name, dev); | ||
| 112 | if (error) { | ||
| 113 | dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n", | ||
| 114 | __func__, __LINE__, error); | ||
| 115 | goto fail_sb_event_receive_port_destroy; | ||
| 116 | } | ||
| 117 | |||
| 118 | alignment = min(__ffs(dev->bounce_size), | ||
| 119 | __ffs((unsigned long)dev->bounce_buf)); | ||
| 120 | if (alignment < 12) { | ||
| 121 | dev_err(&dev->sbd.core, | ||
| 122 | "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n", | ||
| 123 | __func__, __LINE__, dev->bounce_size, dev->bounce_buf); | ||
| 124 | error = -EINVAL; | ||
| 125 | goto fail_free_irq; | ||
| 126 | } else if (alignment < 16) | ||
| 127 | page_size = PS3_DMA_4K; | ||
| 128 | else | ||
| 129 | page_size = PS3_DMA_64K; | ||
| 130 | dev->sbd.d_region = &dev->dma_region; | ||
| 131 | ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size, | ||
| 132 | PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size); | ||
| 133 | res = ps3_dma_region_create(&dev->dma_region); | ||
| 134 | if (res) { | ||
| 135 | dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n", | ||
| 136 | __func__, __LINE__); | ||
| 137 | error = -ENOMEM; | ||
| 138 | goto fail_free_irq; | ||
| 139 | } | ||
| 140 | |||
| 141 | dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf)); | ||
| 142 | dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf, | ||
| 143 | dev->bounce_size, DMA_BIDIRECTIONAL); | ||
| 144 | if (!dev->bounce_dma) { | ||
| 145 | dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n", | ||
| 146 | __func__, __LINE__); | ||
| 147 | error = -ENODEV; | ||
| 148 | goto fail_free_dma; | ||
| 149 | } | ||
| 150 | |||
| 151 | error = ps3stor_probe_access(dev); | ||
| 152 | if (error) { | ||
| 153 | dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n", | ||
| 154 | __func__, __LINE__); | ||
| 155 | goto fail_unmap_dma; | ||
| 156 | } | ||
| 157 | return 0; | ||
| 158 | |||
| 159 | fail_unmap_dma: | ||
| 160 | dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size, | ||
| 161 | DMA_BIDIRECTIONAL); | ||
| 162 | fail_free_dma: | ||
| 163 | ps3_dma_region_free(&dev->dma_region); | ||
| 164 | fail_free_irq: | ||
| 165 | free_irq(dev->irq, dev); | ||
| 166 | fail_sb_event_receive_port_destroy: | ||
| 167 | ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); | ||
| 168 | fail_close_device: | ||
| 169 | ps3_close_hv_device(&dev->sbd); | ||
| 170 | fail: | ||
| 171 | return error; | ||
| 172 | } | ||
| 173 | EXPORT_SYMBOL_GPL(ps3stor_setup); | ||
| 174 | |||
| 175 | |||
| 176 | /** | ||
| 177 | * ps3stor_teardown - Tear down a storage device after use | ||
| 178 | * @dev: Pointer to a struct ps3_storage_device | ||
| 179 | */ | ||
| 180 | void ps3stor_teardown(struct ps3_storage_device *dev) | ||
| 181 | { | ||
| 182 | int error; | ||
| 183 | |||
| 184 | dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size, | ||
| 185 | DMA_BIDIRECTIONAL); | ||
| 186 | ps3_dma_region_free(&dev->dma_region); | ||
| 187 | |||
| 188 | free_irq(dev->irq, dev); | ||
| 189 | |||
| 190 | error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); | ||
| 191 | if (error) | ||
| 192 | dev_err(&dev->sbd.core, | ||
| 193 | "%s:%u: destroy event receive port failed %d\n", | ||
| 194 | __func__, __LINE__, error); | ||
| 195 | |||
| 196 | error = ps3_close_hv_device(&dev->sbd); | ||
| 197 | if (error) | ||
| 198 | dev_err(&dev->sbd.core, | ||
| 199 | "%s:%u: ps3_close_hv_device failed %d\n", __func__, | ||
| 200 | __LINE__, error); | ||
| 201 | } | ||
| 202 | EXPORT_SYMBOL_GPL(ps3stor_teardown); | ||
| 203 | |||
| 204 | |||
| 205 | /** | ||
| 206 | * ps3stor_read_write_sectors - read/write from/to a storage device | ||
| 207 | * @dev: Pointer to a struct ps3_storage_device | ||
| 208 | * @lpar: HV logical partition address | ||
| 209 | * @start_sector: First sector to read/write | ||
| 210 | * @sectors: Number of sectors to read/write | ||
| 211 | * @write: Flag indicating write (non-zero) or read (zero) | ||
| 212 | * | ||
| 213 | * Returns 0 for success, -1 in case of failure to submit the command, or | ||
| 214 | * an LV1 status value in case of other errors | ||
| 215 | */ | ||
| 216 | u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, | ||
| 217 | u64 start_sector, u64 sectors, int write) | ||
| 218 | { | ||
| 219 | unsigned int region_id = dev->regions[dev->region_idx].id; | ||
| 220 | const char *op = write ? "write" : "read"; | ||
| 221 | int res; | ||
| 222 | |||
| 223 | dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n", | ||
| 224 | __func__, __LINE__, op, sectors, start_sector); | ||
| 225 | |||
| 226 | init_completion(&dev->done); | ||
| 227 | res = write ? lv1_storage_write(dev->sbd.dev_id, region_id, | ||
| 228 | start_sector, sectors, 0, lpar, | ||
| 229 | &dev->tag) | ||
| 230 | : lv1_storage_read(dev->sbd.dev_id, region_id, | ||
| 231 | start_sector, sectors, 0, lpar, | ||
| 232 | &dev->tag); | ||
| 233 | if (res) { | ||
| 234 | dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, | ||
| 235 | __LINE__, op, res); | ||
| 236 | return -1; | ||
| 237 | } | ||
| 238 | |||
| 239 | wait_for_completion(&dev->done); | ||
| 240 | if (dev->lv1_status) { | ||
| 241 | dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__, | ||
| 242 | __LINE__, op, dev->lv1_status); | ||
| 243 | return dev->lv1_status; | ||
| 244 | } | ||
| 245 | |||
| 246 | dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__, | ||
| 247 | op); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors); | ||
| 252 | |||
| 253 | |||
| 254 | /** | ||
| 255 | * ps3stor_send_command - send a device command to a storage device | ||
| 256 | * @dev: Pointer to a struct ps3_storage_device | ||
| 257 | * @cmd: Command number | ||
| 258 | * @arg1: First command argument | ||
| 259 | * @arg2: Second command argument | ||
| 260 | * @arg3: Third command argument | ||
| 261 | * @arg4: Fourth command argument | ||
| 262 | * | ||
| 263 | * Returns 0 for success, -1 in case of failure to submit the command, or | ||
| 264 | * an LV1 status value in case of other errors | ||
| 265 | */ | ||
| 266 | u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1, | ||
| 267 | u64 arg2, u64 arg3, u64 arg4) | ||
| 268 | { | ||
| 269 | int res; | ||
| 270 | |||
| 271 | dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__, | ||
| 272 | __LINE__, cmd); | ||
| 273 | |||
| 274 | init_completion(&dev->done); | ||
| 275 | |||
| 276 | res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1, | ||
| 277 | arg2, arg3, arg4, &dev->tag); | ||
| 278 | if (res) { | ||
| 279 | dev_err(&dev->sbd.core, | ||
| 280 | "%s:%u: send_device_command 0x%lx failed %d\n", | ||
| 281 | __func__, __LINE__, cmd, res); | ||
| 282 | return -1; | ||
| 283 | } | ||
| 284 | |||
| 285 | wait_for_completion(&dev->done); | ||
| 286 | if (dev->lv1_status) { | ||
| 287 | dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n", | ||
| 288 | __func__, __LINE__, cmd, dev->lv1_status); | ||
| 289 | return dev->lv1_status; | ||
| 290 | } | ||
| 291 | |||
| 292 | dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__, | ||
| 293 | __LINE__, cmd); | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | EXPORT_SYMBOL_GPL(ps3stor_send_command); | ||
| 298 | |||
| 299 | |||
| 300 | MODULE_LICENSE("GPL"); | ||
| 301 | MODULE_DESCRIPTION("PS3 Storage Bus Library"); | ||
| 302 | MODULE_AUTHOR("Sony Corporation"); | ||
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c new file mode 100644 index 000000000000..31648f7d9ae1 --- /dev/null +++ b/drivers/ps3/sys-manager-core.c | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * PS3 System Manager core. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <asm/ps3.h> | ||
| 23 | |||
| 24 | /** | ||
| 25 | * Staticly linked routines that allow late binding of a loaded sys-manager | ||
| 26 | * module. | ||
| 27 | */ | ||
| 28 | |||
| 29 | static struct ps3_sys_manager_ops ps3_sys_manager_ops; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module. | ||
| 33 | * @ops: struct ps3_sys_manager_ops. | ||
| 34 | * | ||
| 35 | * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to | ||
| 36 | * register call back ops for power control. Copies data to the static | ||
| 37 | * variable ps3_sys_manager_ops. | ||
| 38 | */ | ||
| 39 | |||
| 40 | void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops) | ||
| 41 | { | ||
| 42 | BUG_ON(!ops); | ||
| 43 | BUG_ON(!ops->dev); | ||
| 44 | ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops; | ||
| 45 | } | ||
| 46 | EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops); | ||
| 47 | |||
| 48 | void ps3_sys_manager_power_off(void) | ||
| 49 | { | ||
| 50 | if (ps3_sys_manager_ops.power_off) | ||
| 51 | ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); | ||
| 52 | |||
| 53 | printk(KERN_EMERG "System Halted, OK to turn off power\n"); | ||
| 54 | local_irq_disable(); | ||
| 55 | while (1) | ||
| 56 | (void)0; | ||
| 57 | } | ||
| 58 | |||
| 59 | void ps3_sys_manager_restart(void) | ||
| 60 | { | ||
| 61 | if (ps3_sys_manager_ops.restart) | ||
| 62 | ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); | ||
| 63 | |||
| 64 | printk(KERN_EMERG "System Halted, OK to turn off power\n"); | ||
| 65 | local_irq_disable(); | ||
| 66 | while (1) | ||
| 67 | (void)0; | ||
| 68 | } | ||
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c index 3aa2b0dcc369..8461b08ab9fb 100644 --- a/drivers/ps3/sys-manager.c +++ b/drivers/ps3/sys-manager.c | |||
| @@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager"); | |||
| 35 | /** | 35 | /** |
| 36 | * ps3_sys_manager - PS3 system manager driver. | 36 | * ps3_sys_manager - PS3 system manager driver. |
| 37 | * | 37 | * |
| 38 | * The system manager provides an asyncronous system event notification | 38 | * The system manager provides an asynchronous system event notification |
| 39 | * mechanism for reporting events like thermal alert and button presses to | 39 | * mechanism for reporting events like thermal alert and button presses to |
| 40 | * guests. It also provides support to control system shutdown and startup. | 40 | * guests. It also provides support to control system shutdown and startup. |
| 41 | * | 41 | * |
| @@ -52,6 +52,7 @@ MODULE_DESCRIPTION("PS3 System Manager"); | |||
| 52 | * @size: Header size in bytes, curently 16. | 52 | * @size: Header size in bytes, curently 16. |
| 53 | * @payload_size: Message payload size in bytes. | 53 | * @payload_size: Message payload size in bytes. |
| 54 | * @service_id: Message type, one of enum ps3_sys_manager_service_id. | 54 | * @service_id: Message type, one of enum ps3_sys_manager_service_id. |
| 55 | * @request_tag: Unique number to identify reply. | ||
| 55 | */ | 56 | */ |
| 56 | 57 | ||
| 57 | struct ps3_sys_manager_header { | 58 | struct ps3_sys_manager_header { |
| @@ -61,29 +62,49 @@ struct ps3_sys_manager_header { | |||
| 61 | u16 reserved_1; | 62 | u16 reserved_1; |
| 62 | u32 payload_size; | 63 | u32 payload_size; |
| 63 | u16 service_id; | 64 | u16 service_id; |
| 64 | u16 reserved_2[3]; | 65 | u16 reserved_2; |
| 66 | u32 request_tag; | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 69 | #define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__) | ||
| 70 | static void __maybe_unused _dump_sm_header( | ||
| 71 | const struct ps3_sys_manager_header *h, const char *func, int line) | ||
| 72 | { | ||
| 73 | pr_debug("%s:%d: version: %xh\n", func, line, h->version); | ||
| 74 | pr_debug("%s:%d: size: %xh\n", func, line, h->size); | ||
| 75 | pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size); | ||
| 76 | pr_debug("%s:%d: service_id: %xh\n", func, line, h->service_id); | ||
| 77 | pr_debug("%s:%d: request_tag: %xh\n", func, line, h->request_tag); | ||
| 78 | } | ||
| 79 | |||
| 67 | /** | 80 | /** |
| 68 | * @PS3_SM_RX_MSG_LEN - System manager received message length. | 81 | * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length. |
| 82 | * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length. | ||
| 69 | * | 83 | * |
| 70 | * Currently all messages received from the system manager are the same length | 84 | * Currently all messages received from the system manager are either |
| 71 | * (16 bytes header + 16 bytes payload = 32 bytes). This knowlege is used to | 85 | * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header |
| 72 | * simplify the logic. | 86 | * + 16 bytes payload = 32 bytes). This knowlege is used to simplify |
| 87 | * the logic. | ||
| 73 | */ | 88 | */ |
| 74 | 89 | ||
| 75 | enum { | 90 | enum { |
| 76 | PS3_SM_RX_MSG_LEN = 32, | 91 | PS3_SM_RX_MSG_LEN_MIN = 24, |
| 92 | PS3_SM_RX_MSG_LEN_MAX = 32, | ||
| 77 | }; | 93 | }; |
| 78 | 94 | ||
| 79 | /** | 95 | /** |
| 80 | * enum ps3_sys_manager_service_id - Message header service_id. | 96 | * enum ps3_sys_manager_service_id - Message header service_id. |
| 81 | * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager. | 97 | * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager. |
| 82 | * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager. | 98 | * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager. |
| 83 | * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager. | 99 | * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager. |
| 84 | * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager. | 100 | * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager. |
| 85 | * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager. | 101 | * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager. |
| 86 | * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager. | 102 | * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager. |
| 103 | * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager. | ||
| 104 | * | ||
| 105 | * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a | ||
| 106 | * a PS3_SM_SERVICE_ID_REQUEST message. It also seems to be returned when | ||
| 107 | * a REQUEST message is sent at the wrong time. | ||
| 87 | */ | 108 | */ |
| 88 | 109 | ||
| 89 | enum ps3_sys_manager_service_id { | 110 | enum ps3_sys_manager_service_id { |
| @@ -93,6 +114,7 @@ enum ps3_sys_manager_service_id { | |||
| 93 | PS3_SM_SERVICE_ID_COMMAND = 3, | 114 | PS3_SM_SERVICE_ID_COMMAND = 3, |
| 94 | PS3_SM_SERVICE_ID_EXTERN_EVENT = 4, | 115 | PS3_SM_SERVICE_ID_EXTERN_EVENT = 4, |
| 95 | PS3_SM_SERVICE_ID_SET_NEXT_OP = 5, | 116 | PS3_SM_SERVICE_ID_SET_NEXT_OP = 5, |
| 117 | PS3_SM_SERVICE_ID_REQUEST_ERROR = 6, | ||
| 96 | PS3_SM_SERVICE_ID_SET_ATTR = 8, | 118 | PS3_SM_SERVICE_ID_SET_ATTR = 8, |
| 97 | }; | 119 | }; |
| 98 | 120 | ||
| @@ -185,11 +207,21 @@ enum ps3_sys_manager_cmd { | |||
| 185 | }; | 207 | }; |
| 186 | 208 | ||
| 187 | /** | 209 | /** |
| 210 | * ps3_sm_force_power_off - Poweroff helper. | ||
| 211 | * | ||
| 212 | * A global variable used to force a poweroff when the power button has | ||
| 213 | * been pressed irrespective of how init handles the ctrl_alt_del signal. | ||
| 214 | * | ||
| 215 | */ | ||
| 216 | |||
| 217 | static unsigned int ps3_sm_force_power_off; | ||
| 218 | |||
| 219 | /** | ||
| 188 | * ps3_sys_manager_write - Helper to write a two part message to the vuart. | 220 | * ps3_sys_manager_write - Helper to write a two part message to the vuart. |
| 189 | * | 221 | * |
| 190 | */ | 222 | */ |
| 191 | 223 | ||
| 192 | static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev, | 224 | static int ps3_sys_manager_write(struct ps3_system_bus_device *dev, |
| 193 | const struct ps3_sys_manager_header *header, const void *payload) | 225 | const struct ps3_sys_manager_header *header, const void *payload) |
| 194 | { | 226 | { |
| 195 | int result; | 227 | int result; |
| @@ -213,15 +245,10 @@ static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev, | |||
| 213 | * | 245 | * |
| 214 | */ | 246 | */ |
| 215 | 247 | ||
| 216 | static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev, | 248 | static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev, |
| 217 | enum ps3_sys_manager_attr attr) | 249 | enum ps3_sys_manager_attr attr) |
| 218 | { | 250 | { |
| 219 | static const struct ps3_sys_manager_header header = { | 251 | struct ps3_sys_manager_header header; |
| 220 | .version = 1, | ||
| 221 | .size = 16, | ||
| 222 | .payload_size = 16, | ||
| 223 | .service_id = PS3_SM_SERVICE_ID_SET_ATTR, | ||
| 224 | }; | ||
| 225 | struct { | 252 | struct { |
| 226 | u8 version; | 253 | u8 version; |
| 227 | u8 reserved_1[3]; | 254 | u8 reserved_1[3]; |
| @@ -232,6 +259,12 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev, | |||
| 232 | 259 | ||
| 233 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr); | 260 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr); |
| 234 | 261 | ||
| 262 | memset(&header, 0, sizeof(header)); | ||
| 263 | header.version = 1; | ||
| 264 | header.size = 16; | ||
| 265 | header.payload_size = 16; | ||
| 266 | header.service_id = PS3_SM_SERVICE_ID_SET_ATTR; | ||
| 267 | |||
| 235 | memset(&payload, 0, sizeof(payload)); | 268 | memset(&payload, 0, sizeof(payload)); |
| 236 | payload.version = 1; | 269 | payload.version = 1; |
| 237 | payload.attribute = attr; | 270 | payload.attribute = attr; |
| @@ -245,16 +278,11 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev, | |||
| 245 | * Tell the system manager what to do after this lpar is destroyed. | 278 | * Tell the system manager what to do after this lpar is destroyed. |
| 246 | */ | 279 | */ |
| 247 | 280 | ||
| 248 | static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev, | 281 | static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev, |
| 249 | enum ps3_sys_manager_next_op op, | 282 | enum ps3_sys_manager_next_op op, |
| 250 | enum ps3_sys_manager_wake_source wake_source) | 283 | enum ps3_sys_manager_wake_source wake_source) |
| 251 | { | 284 | { |
| 252 | static const struct ps3_sys_manager_header header = { | 285 | struct ps3_sys_manager_header header; |
| 253 | .version = 1, | ||
| 254 | .size = 16, | ||
| 255 | .payload_size = 16, | ||
| 256 | .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP, | ||
| 257 | }; | ||
| 258 | struct { | 286 | struct { |
| 259 | u8 version; | 287 | u8 version; |
| 260 | u8 type; | 288 | u8 type; |
| @@ -268,6 +296,12 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev, | |||
| 268 | 296 | ||
| 269 | dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op); | 297 | dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op); |
| 270 | 298 | ||
| 299 | memset(&header, 0, sizeof(header)); | ||
| 300 | header.version = 1; | ||
| 301 | header.size = 16; | ||
| 302 | header.payload_size = 16; | ||
| 303 | header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP; | ||
| 304 | |||
| 271 | memset(&payload, 0, sizeof(payload)); | 305 | memset(&payload, 0, sizeof(payload)); |
| 272 | payload.version = 3; | 306 | payload.version = 3; |
| 273 | payload.type = op; | 307 | payload.type = op; |
| @@ -286,32 +320,35 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev, | |||
| 286 | * the command is then communicated back to the system manager with a response | 320 | * the command is then communicated back to the system manager with a response |
| 287 | * message. | 321 | * message. |
| 288 | * | 322 | * |
| 289 | * Currently, the only supported request it the 'shutdown self' request. | 323 | * Currently, the only supported request is the 'shutdown self' request. |
| 290 | */ | 324 | */ |
| 291 | 325 | ||
| 292 | static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev) | 326 | static int ps3_sys_manager_send_request_shutdown( |
| 327 | struct ps3_system_bus_device *dev) | ||
| 293 | { | 328 | { |
| 294 | static const struct ps3_sys_manager_header header = { | 329 | struct ps3_sys_manager_header header; |
| 295 | .version = 1, | ||
| 296 | .size = 16, | ||
| 297 | .payload_size = 16, | ||
| 298 | .service_id = PS3_SM_SERVICE_ID_REQUEST, | ||
| 299 | }; | ||
| 300 | struct { | 330 | struct { |
| 301 | u8 version; | 331 | u8 version; |
| 302 | u8 type; | 332 | u8 type; |
| 303 | u8 gos_id; | 333 | u8 gos_id; |
| 304 | u8 reserved_1[13]; | 334 | u8 reserved_1[13]; |
| 305 | } static const payload = { | 335 | } payload; |
| 306 | .version = 1, | ||
| 307 | .type = 1, /* shutdown */ | ||
| 308 | .gos_id = 0, /* self */ | ||
| 309 | }; | ||
| 310 | 336 | ||
| 311 | BUILD_BUG_ON(sizeof(payload) != 16); | 337 | BUILD_BUG_ON(sizeof(payload) != 16); |
| 312 | 338 | ||
| 313 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 339 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 314 | 340 | ||
| 341 | memset(&header, 0, sizeof(header)); | ||
| 342 | header.version = 1; | ||
| 343 | header.size = 16; | ||
| 344 | header.payload_size = 16; | ||
| 345 | header.service_id = PS3_SM_SERVICE_ID_REQUEST; | ||
| 346 | |||
| 347 | memset(&payload, 0, sizeof(payload)); | ||
| 348 | payload.version = 1; | ||
| 349 | payload.type = 1; /* shutdown */ | ||
| 350 | payload.gos_id = 0; /* self */ | ||
| 351 | |||
| 315 | return ps3_sys_manager_write(dev, &header, &payload); | 352 | return ps3_sys_manager_write(dev, &header, &payload); |
| 316 | } | 353 | } |
| 317 | 354 | ||
| @@ -323,15 +360,10 @@ static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *d | |||
| 323 | * failure of a command sent by the system manager. | 360 | * failure of a command sent by the system manager. |
| 324 | */ | 361 | */ |
| 325 | 362 | ||
| 326 | static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev, | 363 | static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev, |
| 327 | u64 status) | 364 | u64 status) |
| 328 | { | 365 | { |
| 329 | static const struct ps3_sys_manager_header header = { | 366 | struct ps3_sys_manager_header header; |
| 330 | .version = 1, | ||
| 331 | .size = 16, | ||
| 332 | .payload_size = 16, | ||
| 333 | .service_id = PS3_SM_SERVICE_ID_RESPONSE, | ||
| 334 | }; | ||
| 335 | struct { | 367 | struct { |
| 336 | u8 version; | 368 | u8 version; |
| 337 | u8 reserved_1[3]; | 369 | u8 reserved_1[3]; |
| @@ -344,6 +376,12 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev, | |||
| 344 | dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, | 376 | dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, |
| 345 | (status ? "nak" : "ack")); | 377 | (status ? "nak" : "ack")); |
| 346 | 378 | ||
| 379 | memset(&header, 0, sizeof(header)); | ||
| 380 | header.version = 1; | ||
| 381 | header.size = 16; | ||
| 382 | header.payload_size = 16; | ||
| 383 | header.service_id = PS3_SM_SERVICE_ID_RESPONSE; | ||
| 384 | |||
| 347 | memset(&payload, 0, sizeof(payload)); | 385 | memset(&payload, 0, sizeof(payload)); |
| 348 | payload.version = 1; | 386 | payload.version = 1; |
| 349 | payload.status = status; | 387 | payload.status = status; |
| @@ -356,7 +394,7 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev, | |||
| 356 | * | 394 | * |
| 357 | */ | 395 | */ |
| 358 | 396 | ||
| 359 | static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) | 397 | static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) |
| 360 | { | 398 | { |
| 361 | int result; | 399 | int result; |
| 362 | struct { | 400 | struct { |
| @@ -370,7 +408,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) | |||
| 370 | BUILD_BUG_ON(sizeof(event) != 16); | 408 | BUILD_BUG_ON(sizeof(event) != 16); |
| 371 | 409 | ||
| 372 | result = ps3_vuart_read(dev, &event, sizeof(event)); | 410 | result = ps3_vuart_read(dev, &event, sizeof(event)); |
| 373 | BUG_ON(result); | 411 | BUG_ON(result && "need to retry here"); |
| 374 | 412 | ||
| 375 | if (event.version != 1) { | 413 | if (event.version != 1) { |
| 376 | dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n", | 414 | dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n", |
| @@ -382,11 +420,34 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) | |||
| 382 | case PS3_SM_EVENT_POWER_PRESSED: | 420 | case PS3_SM_EVENT_POWER_PRESSED: |
| 383 | dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n", | 421 | dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n", |
| 384 | __func__, __LINE__); | 422 | __func__, __LINE__); |
| 423 | ps3_sm_force_power_off = 1; | ||
| 424 | /* | ||
| 425 | * A memory barrier is use here to sync memory since | ||
| 426 | * ps3_sys_manager_final_restart() could be called on | ||
| 427 | * another cpu. | ||
| 428 | */ | ||
| 429 | wmb(); | ||
| 430 | kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */ | ||
| 385 | break; | 431 | break; |
| 386 | case PS3_SM_EVENT_POWER_RELEASED: | 432 | case PS3_SM_EVENT_POWER_RELEASED: |
| 387 | dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n", | 433 | dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n", |
| 388 | __func__, __LINE__, event.value); | 434 | __func__, __LINE__, event.value); |
| 389 | kill_cad_pid(SIGINT, 1); | 435 | break; |
| 436 | case PS3_SM_EVENT_RESET_PRESSED: | ||
| 437 | dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n", | ||
| 438 | __func__, __LINE__); | ||
| 439 | ps3_sm_force_power_off = 0; | ||
| 440 | /* | ||
| 441 | * A memory barrier is use here to sync memory since | ||
| 442 | * ps3_sys_manager_final_restart() could be called on | ||
| 443 | * another cpu. | ||
| 444 | */ | ||
| 445 | wmb(); | ||
| 446 | kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */ | ||
| 447 | break; | ||
| 448 | case PS3_SM_EVENT_RESET_RELEASED: | ||
| 449 | dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n", | ||
| 450 | __func__, __LINE__, event.value); | ||
| 390 | break; | 451 | break; |
| 391 | case PS3_SM_EVENT_THERMAL_ALERT: | 452 | case PS3_SM_EVENT_THERMAL_ALERT: |
| 392 | dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n", | 453 | dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n", |
| @@ -411,7 +472,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) | |||
| 411 | * The system manager sends this in reply to a 'request' message from the guest. | 472 | * The system manager sends this in reply to a 'request' message from the guest. |
| 412 | */ | 473 | */ |
| 413 | 474 | ||
| 414 | static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev) | 475 | static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev) |
| 415 | { | 476 | { |
| 416 | int result; | 477 | int result; |
| 417 | struct { | 478 | struct { |
| @@ -425,6 +486,7 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev) | |||
| 425 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 486 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 426 | 487 | ||
| 427 | result = ps3_vuart_read(dev, &cmd, sizeof(cmd)); | 488 | result = ps3_vuart_read(dev, &cmd, sizeof(cmd)); |
| 489 | BUG_ON(result && "need to retry here"); | ||
| 428 | 490 | ||
| 429 | if(result) | 491 | if(result) |
| 430 | return result; | 492 | return result; |
| @@ -448,9 +510,10 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev) | |||
| 448 | /** | 510 | /** |
| 449 | * ps3_sys_manager_handle_msg - First stage msg handler. | 511 | * ps3_sys_manager_handle_msg - First stage msg handler. |
| 450 | * | 512 | * |
| 513 | * Can be called directly to manually poll vuart and pump message handler. | ||
| 451 | */ | 514 | */ |
| 452 | 515 | ||
| 453 | static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev) | 516 | static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev) |
| 454 | { | 517 | { |
| 455 | int result; | 518 | int result; |
| 456 | struct ps3_sys_manager_header header; | 519 | struct ps3_sys_manager_header header; |
| @@ -464,12 +527,17 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev) | |||
| 464 | if (header.version != 1) { | 527 | if (header.version != 1) { |
| 465 | dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n", | 528 | dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n", |
| 466 | __func__, __LINE__, header.version); | 529 | __func__, __LINE__, header.version); |
| 530 | dump_sm_header(&header); | ||
| 467 | goto fail_header; | 531 | goto fail_header; |
| 468 | } | 532 | } |
| 469 | 533 | ||
| 470 | BUILD_BUG_ON(sizeof(header) != 16); | 534 | BUILD_BUG_ON(sizeof(header) != 16); |
| 471 | BUG_ON(header.size != 16); | 535 | |
| 472 | BUG_ON(header.payload_size != 16); | 536 | if (header.size != 16 || (header.payload_size != 8 |
| 537 | && header.payload_size != 16)) { | ||
| 538 | dump_sm_header(&header); | ||
| 539 | BUG(); | ||
| 540 | } | ||
| 473 | 541 | ||
| 474 | switch (header.service_id) { | 542 | switch (header.service_id) { |
| 475 | case PS3_SM_SERVICE_ID_EXTERN_EVENT: | 543 | case PS3_SM_SERVICE_ID_EXTERN_EVENT: |
| @@ -478,6 +546,11 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev) | |||
| 478 | case PS3_SM_SERVICE_ID_COMMAND: | 546 | case PS3_SM_SERVICE_ID_COMMAND: |
| 479 | dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__); | 547 | dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__); |
| 480 | return ps3_sys_manager_handle_cmd(dev); | 548 | return ps3_sys_manager_handle_cmd(dev); |
| 549 | case PS3_SM_SERVICE_ID_REQUEST_ERROR: | ||
| 550 | dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__, | ||
| 551 | __LINE__); | ||
| 552 | dump_sm_header(&header); | ||
| 553 | break; | ||
| 481 | default: | 554 | default: |
| 482 | dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n", | 555 | dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n", |
| 483 | __func__, __LINE__, header.service_id); | 556 | __func__, __LINE__, header.service_id); |
| @@ -494,45 +567,25 @@ fail_id: | |||
| 494 | } | 567 | } |
| 495 | 568 | ||
| 496 | /** | 569 | /** |
| 497 | * ps3_sys_manager_work - Asyncronous read handler. | 570 | * ps3_sys_manager_final_power_off - The final platform machine_power_off routine. |
| 498 | * | ||
| 499 | * Signaled when a complete message arrives at the vuart port. | ||
| 500 | */ | ||
| 501 | |||
| 502 | static void ps3_sys_manager_work(struct work_struct *work) | ||
| 503 | { | ||
| 504 | struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work); | ||
| 505 | |||
| 506 | ps3_sys_manager_handle_msg(dev); | ||
| 507 | ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN); | ||
| 508 | } | ||
| 509 | |||
| 510 | struct { | ||
| 511 | struct ps3_vuart_port_device *dev; | ||
| 512 | } static drv_priv; | ||
| 513 | |||
| 514 | /** | ||
| 515 | * ps3_sys_manager_restart - The final platform machine_restart routine. | ||
| 516 | * | 571 | * |
| 517 | * This routine never returns. The routine disables asyncronous vuart reads | 572 | * This routine never returns. The routine disables asynchronous vuart reads |
| 518 | * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge | 573 | * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge |
| 519 | * the shutdown command sent from the system manager. Soon after the | 574 | * the shutdown command sent from the system manager. Soon after the |
| 520 | * acknowledgement is sent the lpar is destroyed by the HV. This routine | 575 | * acknowledgement is sent the lpar is destroyed by the HV. This routine |
| 521 | * should only be called from ps3_restart(). | 576 | * should only be called from ps3_power_off() through |
| 577 | * ps3_sys_manager_ops.power_off. | ||
| 522 | */ | 578 | */ |
| 523 | 579 | ||
| 524 | void ps3_sys_manager_restart(void) | 580 | static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev) |
| 525 | { | 581 | { |
| 526 | struct ps3_vuart_port_device *dev = drv_priv.dev; | 582 | BUG_ON(!dev); |
| 527 | |||
| 528 | BUG_ON(!drv_priv.dev); | ||
| 529 | 583 | ||
| 530 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 584 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 531 | 585 | ||
| 532 | ps3_vuart_cancel_async(dev); | 586 | ps3_vuart_cancel_async(dev); |
| 533 | 587 | ||
| 534 | ps3_sys_manager_send_attr(dev, 0); | 588 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, |
| 535 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT, | ||
| 536 | PS3_SM_WAKE_DEFAULT); | 589 | PS3_SM_WAKE_DEFAULT); |
| 537 | ps3_sys_manager_send_request_shutdown(dev); | 590 | ps3_sys_manager_send_request_shutdown(dev); |
| 538 | 591 | ||
| @@ -543,26 +596,33 @@ void ps3_sys_manager_restart(void) | |||
| 543 | } | 596 | } |
| 544 | 597 | ||
| 545 | /** | 598 | /** |
| 546 | * ps3_sys_manager_power_off - The final platform machine_power_off routine. | 599 | * ps3_sys_manager_final_restart - The final platform machine_restart routine. |
| 547 | * | 600 | * |
| 548 | * This routine never returns. The routine disables asyncronous vuart reads | 601 | * This routine never returns. The routine disables asynchronous vuart reads |
| 549 | * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge | 602 | * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge |
| 550 | * the shutdown command sent from the system manager. Soon after the | 603 | * the shutdown command sent from the system manager. Soon after the |
| 551 | * acknowledgement is sent the lpar is destroyed by the HV. This routine | 604 | * acknowledgement is sent the lpar is destroyed by the HV. This routine |
| 552 | * should only be called from ps3_power_off(). | 605 | * should only be called from ps3_restart() through ps3_sys_manager_ops.restart. |
| 553 | */ | 606 | */ |
| 554 | 607 | ||
| 555 | void ps3_sys_manager_power_off(void) | 608 | static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev) |
| 556 | { | 609 | { |
| 557 | struct ps3_vuart_port_device *dev = drv_priv.dev; | 610 | BUG_ON(!dev); |
| 558 | |||
| 559 | BUG_ON(!drv_priv.dev); | ||
| 560 | 611 | ||
| 561 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 612 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 562 | 613 | ||
| 614 | /* Check if we got here via a power button event. */ | ||
| 615 | |||
| 616 | if (ps3_sm_force_power_off) { | ||
| 617 | dev_dbg(&dev->core, "%s:%d: forcing poweroff\n", | ||
| 618 | __func__, __LINE__); | ||
| 619 | ps3_sys_manager_final_power_off(dev); | ||
| 620 | } | ||
| 621 | |||
| 563 | ps3_vuart_cancel_async(dev); | 622 | ps3_vuart_cancel_async(dev); |
| 564 | 623 | ||
| 565 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, | 624 | ps3_sys_manager_send_attr(dev, 0); |
| 625 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT, | ||
| 566 | PS3_SM_WAKE_DEFAULT); | 626 | PS3_SM_WAKE_DEFAULT); |
| 567 | ps3_sys_manager_send_request_shutdown(dev); | 627 | ps3_sys_manager_send_request_shutdown(dev); |
| 568 | 628 | ||
| @@ -572,31 +632,60 @@ void ps3_sys_manager_power_off(void) | |||
| 572 | ps3_sys_manager_handle_msg(dev); | 632 | ps3_sys_manager_handle_msg(dev); |
| 573 | } | 633 | } |
| 574 | 634 | ||
| 575 | static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev) | 635 | /** |
| 636 | * ps3_sys_manager_work - Asynchronous read handler. | ||
| 637 | * | ||
| 638 | * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port. | ||
| 639 | */ | ||
| 640 | |||
| 641 | static void ps3_sys_manager_work(struct ps3_system_bus_device *dev) | ||
| 642 | { | ||
| 643 | ps3_sys_manager_handle_msg(dev); | ||
| 644 | ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN); | ||
| 645 | } | ||
| 646 | |||
| 647 | static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev) | ||
| 576 | { | 648 | { |
| 577 | int result; | 649 | int result; |
| 650 | struct ps3_sys_manager_ops ops; | ||
| 578 | 651 | ||
| 579 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 652 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 580 | 653 | ||
| 581 | BUG_ON(drv_priv.dev); | 654 | ops.power_off = ps3_sys_manager_final_power_off; |
| 582 | drv_priv.dev = dev; | 655 | ops.restart = ps3_sys_manager_final_restart; |
| 656 | ops.dev = dev; | ||
| 657 | |||
| 658 | /* ps3_sys_manager_register_ops copies ops. */ | ||
| 659 | |||
| 660 | ps3_sys_manager_register_ops(&ops); | ||
| 583 | 661 | ||
| 584 | result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL); | 662 | result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL); |
| 585 | BUG_ON(result); | 663 | BUG_ON(result); |
| 586 | 664 | ||
| 587 | result = ps3_vuart_read_async(dev, ps3_sys_manager_work, | 665 | result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN); |
| 588 | PS3_SM_RX_MSG_LEN); | ||
| 589 | BUG_ON(result); | 666 | BUG_ON(result); |
| 590 | 667 | ||
| 591 | return result; | 668 | return result; |
| 592 | } | 669 | } |
| 593 | 670 | ||
| 671 | static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev) | ||
| 672 | { | ||
| 673 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
| 674 | return 0; | ||
| 675 | } | ||
| 676 | |||
| 677 | static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev) | ||
| 678 | { | ||
| 679 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
| 680 | } | ||
| 681 | |||
| 594 | static struct ps3_vuart_port_driver ps3_sys_manager = { | 682 | static struct ps3_vuart_port_driver ps3_sys_manager = { |
| 595 | .match_id = PS3_MATCH_ID_SYSTEM_MANAGER, | 683 | .core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER, |
| 596 | .core = { | 684 | .core.core.name = "ps3_sys_manager", |
| 597 | .name = "ps3_sys_manager", | ||
| 598 | }, | ||
| 599 | .probe = ps3_sys_manager_probe, | 685 | .probe = ps3_sys_manager_probe, |
| 686 | .remove = ps3_sys_manager_remove, | ||
| 687 | .shutdown = ps3_sys_manager_shutdown, | ||
| 688 | .work = ps3_sys_manager_work, | ||
| 600 | }; | 689 | }; |
| 601 | 690 | ||
| 602 | static int __init ps3_sys_manager_init(void) | 691 | static int __init ps3_sys_manager_init(void) |
| @@ -608,3 +697,6 @@ static int __init ps3_sys_manager_init(void) | |||
| 608 | } | 697 | } |
| 609 | 698 | ||
| 610 | module_init(ps3_sys_manager_init); | 699 | module_init(ps3_sys_manager_init); |
| 700 | /* Module remove not supported. */ | ||
| 701 | |||
| 702 | MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER); | ||
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c index ec2d36a1bc67..bea25a1391ee 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/vuart.c | |||
| @@ -71,6 +71,34 @@ enum vuart_interrupt_mask { | |||
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | /** | 73 | /** |
| 74 | * struct ps3_vuart_port_priv - private vuart device data. | ||
| 75 | */ | ||
| 76 | |||
| 77 | struct ps3_vuart_port_priv { | ||
| 78 | u64 interrupt_mask; | ||
| 79 | |||
| 80 | struct { | ||
| 81 | spinlock_t lock; | ||
| 82 | struct list_head head; | ||
| 83 | } tx_list; | ||
| 84 | struct { | ||
| 85 | struct ps3_vuart_work work; | ||
| 86 | unsigned long bytes_held; | ||
| 87 | spinlock_t lock; | ||
| 88 | struct list_head head; | ||
| 89 | } rx_list; | ||
| 90 | struct ps3_vuart_stats stats; | ||
| 91 | }; | ||
| 92 | |||
| 93 | static struct ps3_vuart_port_priv *to_port_priv( | ||
| 94 | struct ps3_system_bus_device *dev) | ||
| 95 | { | ||
| 96 | BUG_ON(!dev); | ||
| 97 | BUG_ON(!dev->driver_priv); | ||
| 98 | return (struct ps3_vuart_port_priv *)dev->driver_priv; | ||
| 99 | } | ||
| 100 | |||
| 101 | /** | ||
| 74 | * struct ports_bmp - bitmap indicating ports needing service. | 102 | * struct ports_bmp - bitmap indicating ports needing service. |
| 75 | * | 103 | * |
| 76 | * A 256 bit read only bitmap indicating ports needing service. Do not write | 104 | * A 256 bit read only bitmap indicating ports needing service. Do not write |
| @@ -83,31 +111,14 @@ struct ports_bmp { | |||
| 83 | } __attribute__ ((aligned (32))); | 111 | } __attribute__ ((aligned (32))); |
| 84 | 112 | ||
| 85 | #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) | 113 | #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) |
| 86 | static void __attribute__ ((unused)) _dump_ports_bmp( | 114 | static void __maybe_unused _dump_ports_bmp( |
| 87 | const struct ports_bmp* bmp, const char* func, int line) | 115 | const struct ports_bmp* bmp, const char* func, int line) |
| 88 | { | 116 | { |
| 89 | pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); | 117 | pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); |
| 90 | } | 118 | } |
| 91 | 119 | ||
| 92 | static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id, | ||
| 93 | unsigned int *port_number) | ||
| 94 | { | ||
| 95 | switch(match_id) { | ||
| 96 | case PS3_MATCH_ID_AV_SETTINGS: | ||
| 97 | *port_number = 0; | ||
| 98 | return 0; | ||
| 99 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
| 100 | *port_number = 2; | ||
| 101 | return 0; | ||
| 102 | default: | ||
| 103 | WARN_ON(1); | ||
| 104 | *port_number = UINT_MAX; | ||
| 105 | return -EINVAL; | ||
| 106 | }; | ||
| 107 | } | ||
| 108 | |||
| 109 | #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) | 120 | #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) |
| 110 | static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, | 121 | static void __maybe_unused _dump_port_params(unsigned int port_number, |
| 111 | const char* func, int line) | 122 | const char* func, int line) |
| 112 | { | 123 | { |
| 113 | #if defined(DEBUG) | 124 | #if defined(DEBUG) |
| @@ -144,14 +155,14 @@ struct vuart_triggers { | |||
| 144 | unsigned long tx; | 155 | unsigned long tx; |
| 145 | }; | 156 | }; |
| 146 | 157 | ||
| 147 | int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | 158 | int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev, |
| 148 | struct vuart_triggers *trig) | 159 | struct vuart_triggers *trig) |
| 149 | { | 160 | { |
| 150 | int result; | 161 | int result; |
| 151 | unsigned long size; | 162 | unsigned long size; |
| 152 | unsigned long val; | 163 | unsigned long val; |
| 153 | 164 | ||
| 154 | result = lv1_get_virtual_uart_param(dev->priv->port_number, | 165 | result = lv1_get_virtual_uart_param(dev->port_number, |
| 155 | PARAM_TX_TRIGGER, &trig->tx); | 166 | PARAM_TX_TRIGGER, &trig->tx); |
| 156 | 167 | ||
| 157 | if (result) { | 168 | if (result) { |
| @@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
| 160 | return result; | 171 | return result; |
| 161 | } | 172 | } |
| 162 | 173 | ||
| 163 | result = lv1_get_virtual_uart_param(dev->priv->port_number, | 174 | result = lv1_get_virtual_uart_param(dev->port_number, |
| 164 | PARAM_RX_BUF_SIZE, &size); | 175 | PARAM_RX_BUF_SIZE, &size); |
| 165 | 176 | ||
| 166 | if (result) { | 177 | if (result) { |
| @@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
| 169 | return result; | 180 | return result; |
| 170 | } | 181 | } |
| 171 | 182 | ||
| 172 | result = lv1_get_virtual_uart_param(dev->priv->port_number, | 183 | result = lv1_get_virtual_uart_param(dev->port_number, |
| 173 | PARAM_RX_TRIGGER, &val); | 184 | PARAM_RX_TRIGGER, &val); |
| 174 | 185 | ||
| 175 | if (result) { | 186 | if (result) { |
| @@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
| 186 | return result; | 197 | return result; |
| 187 | } | 198 | } |
| 188 | 199 | ||
| 189 | int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | 200 | int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx, |
| 190 | unsigned int rx) | 201 | unsigned int rx) |
| 191 | { | 202 | { |
| 192 | int result; | 203 | int result; |
| 193 | unsigned long size; | 204 | unsigned long size; |
| 194 | 205 | ||
| 195 | result = lv1_set_virtual_uart_param(dev->priv->port_number, | 206 | result = lv1_set_virtual_uart_param(dev->port_number, |
| 196 | PARAM_TX_TRIGGER, tx); | 207 | PARAM_TX_TRIGGER, tx); |
| 197 | 208 | ||
| 198 | if (result) { | 209 | if (result) { |
| @@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
| 201 | return result; | 212 | return result; |
| 202 | } | 213 | } |
| 203 | 214 | ||
| 204 | result = lv1_get_virtual_uart_param(dev->priv->port_number, | 215 | result = lv1_get_virtual_uart_param(dev->port_number, |
| 205 | PARAM_RX_BUF_SIZE, &size); | 216 | PARAM_RX_BUF_SIZE, &size); |
| 206 | 217 | ||
| 207 | if (result) { | 218 | if (result) { |
| @@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
| 210 | return result; | 221 | return result; |
| 211 | } | 222 | } |
| 212 | 223 | ||
| 213 | result = lv1_set_virtual_uart_param(dev->priv->port_number, | 224 | result = lv1_set_virtual_uart_param(dev->port_number, |
| 214 | PARAM_RX_TRIGGER, size - rx); | 225 | PARAM_RX_TRIGGER, size - rx); |
| 215 | 226 | ||
| 216 | if (result) { | 227 | if (result) { |
| @@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
| 225 | return result; | 236 | return result; |
| 226 | } | 237 | } |
| 227 | 238 | ||
| 228 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, | 239 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev, |
| 229 | u64 *bytes_waiting) | 240 | u64 *bytes_waiting) |
| 230 | { | 241 | { |
| 231 | int result = lv1_get_virtual_uart_param(dev->priv->port_number, | 242 | int result; |
| 243 | |||
| 244 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
| 232 | PARAM_RX_BYTES, bytes_waiting); | 245 | PARAM_RX_BYTES, bytes_waiting); |
| 233 | 246 | ||
| 234 | if (result) | 247 | if (result) |
| @@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, | |||
| 240 | return result; | 253 | return result; |
| 241 | } | 254 | } |
| 242 | 255 | ||
| 243 | static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, | 256 | /** |
| 257 | * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources. | ||
| 258 | * @dev: The struct ps3_system_bus_device instance. | ||
| 259 | * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables. | ||
| 260 | */ | ||
| 261 | |||
| 262 | static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev, | ||
| 244 | unsigned long mask) | 263 | unsigned long mask) |
| 245 | { | 264 | { |
| 246 | int result; | 265 | int result; |
| 266 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 247 | 267 | ||
| 248 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); | 268 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); |
| 249 | 269 | ||
| 250 | dev->priv->interrupt_mask = mask; | 270 | priv->interrupt_mask = mask; |
| 251 | 271 | ||
| 252 | result = lv1_set_virtual_uart_param(dev->priv->port_number, | 272 | result = lv1_set_virtual_uart_param(dev->port_number, |
| 253 | PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask); | 273 | PARAM_INTERRUPT_MASK, priv->interrupt_mask); |
| 254 | 274 | ||
| 255 | if (result) | 275 | if (result) |
| 256 | dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", | 276 | dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", |
| @@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, | |||
| 259 | return result; | 279 | return result; |
| 260 | } | 280 | } |
| 261 | 281 | ||
| 262 | static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, | 282 | static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev, |
| 263 | unsigned long *status) | 283 | unsigned long *status) |
| 264 | { | 284 | { |
| 285 | int result; | ||
| 286 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 265 | u64 tmp; | 287 | u64 tmp; |
| 266 | int result = lv1_get_virtual_uart_param(dev->priv->port_number, | 288 | |
| 289 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
| 267 | PARAM_INTERRUPT_STATUS, &tmp); | 290 | PARAM_INTERRUPT_STATUS, &tmp); |
| 268 | 291 | ||
| 269 | if (result) | 292 | if (result) |
| 270 | dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", | 293 | dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", |
| 271 | __func__, __LINE__, ps3_result(result)); | 294 | __func__, __LINE__, ps3_result(result)); |
| 272 | 295 | ||
| 273 | *status = tmp & dev->priv->interrupt_mask; | 296 | *status = tmp & priv->interrupt_mask; |
| 274 | 297 | ||
| 275 | dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", | 298 | dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", |
| 276 | __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status); | 299 | __func__, __LINE__, priv->interrupt_mask, tmp, *status); |
| 277 | 300 | ||
| 278 | return result; | 301 | return result; |
| 279 | } | 302 | } |
| 280 | 303 | ||
| 281 | int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) | 304 | int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev) |
| 282 | { | 305 | { |
| 283 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 | 306 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 284 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 307 | |
| 308 | return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 | ||
| 309 | : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 285 | | INTERRUPT_MASK_TX); | 310 | | INTERRUPT_MASK_TX); |
| 286 | } | 311 | } |
| 287 | 312 | ||
| 288 | int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) | 313 | int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev) |
| 289 | { | 314 | { |
| 290 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 | 315 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 291 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 316 | |
| 317 | return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 | ||
| 318 | : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 292 | | INTERRUPT_MASK_RX); | 319 | | INTERRUPT_MASK_RX); |
| 293 | } | 320 | } |
| 294 | 321 | ||
| 295 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 322 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev) |
| 296 | { | 323 | { |
| 297 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 | 324 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 298 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 325 | |
| 326 | return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 | ||
| 327 | : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 299 | | INTERRUPT_MASK_DISCONNECT); | 328 | | INTERRUPT_MASK_DISCONNECT); |
| 300 | } | 329 | } |
| 301 | 330 | ||
| 302 | int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) | 331 | int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev) |
| 303 | { | 332 | { |
| 304 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) | 333 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 305 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 334 | |
| 335 | return (priv->interrupt_mask & INTERRUPT_MASK_TX) | ||
| 336 | ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 306 | & ~INTERRUPT_MASK_TX) : 0; | 337 | & ~INTERRUPT_MASK_TX) : 0; |
| 307 | } | 338 | } |
| 308 | 339 | ||
| 309 | int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) | 340 | int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev) |
| 310 | { | 341 | { |
| 311 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) | 342 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 312 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 343 | |
| 344 | return (priv->interrupt_mask & INTERRUPT_MASK_RX) | ||
| 345 | ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 313 | & ~INTERRUPT_MASK_RX) : 0; | 346 | & ~INTERRUPT_MASK_RX) : 0; |
| 314 | } | 347 | } |
| 315 | 348 | ||
| 316 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 349 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev) |
| 317 | { | 350 | { |
| 318 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) | 351 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 319 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | 352 | |
| 353 | return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) | ||
| 354 | ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask | ||
| 320 | & ~INTERRUPT_MASK_DISCONNECT) : 0; | 355 | & ~INTERRUPT_MASK_DISCONNECT) : 0; |
| 321 | } | 356 | } |
| 322 | 357 | ||
| 323 | /** | 358 | /** |
| 324 | * ps3_vuart_raw_write - Low level write helper. | 359 | * ps3_vuart_raw_write - Low level write helper. |
| 360 | * @dev: The struct ps3_system_bus_device instance. | ||
| 325 | * | 361 | * |
| 326 | * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. | 362 | * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. |
| 327 | */ | 363 | */ |
| 328 | 364 | ||
| 329 | static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | 365 | static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev, |
| 330 | const void* buf, unsigned int bytes, unsigned long *bytes_written) | 366 | const void* buf, unsigned int bytes, unsigned long *bytes_written) |
| 331 | { | 367 | { |
| 332 | int result; | 368 | int result; |
| 369 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 333 | 370 | ||
| 334 | result = lv1_write_virtual_uart(dev->priv->port_number, | 371 | result = lv1_write_virtual_uart(dev->port_number, |
| 335 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); | 372 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); |
| 336 | 373 | ||
| 337 | if (result) { | 374 | if (result) { |
| @@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | |||
| 340 | return result; | 377 | return result; |
| 341 | } | 378 | } |
| 342 | 379 | ||
| 343 | dev->priv->stats.bytes_written += *bytes_written; | 380 | priv->stats.bytes_written += *bytes_written; |
| 344 | 381 | ||
| 345 | dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, | 382 | dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, |
| 346 | *bytes_written, bytes, dev->priv->stats.bytes_written); | 383 | *bytes_written, bytes, priv->stats.bytes_written); |
| 347 | 384 | ||
| 348 | return result; | 385 | return result; |
| 349 | } | 386 | } |
| 350 | 387 | ||
| 351 | /** | 388 | /** |
| 352 | * ps3_vuart_raw_read - Low level read helper. | 389 | * ps3_vuart_raw_read - Low level read helper. |
| 390 | * @dev: The struct ps3_system_bus_device instance. | ||
| 353 | * | 391 | * |
| 354 | * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. | 392 | * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. |
| 355 | */ | 393 | */ |
| 356 | 394 | ||
| 357 | static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | 395 | static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf, |
| 358 | unsigned int bytes, unsigned long *bytes_read) | 396 | unsigned int bytes, unsigned long *bytes_read) |
| 359 | { | 397 | { |
| 360 | int result; | 398 | int result; |
| 399 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 361 | 400 | ||
| 362 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); | 401 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); |
| 363 | 402 | ||
| 364 | result = lv1_read_virtual_uart(dev->priv->port_number, | 403 | result = lv1_read_virtual_uart(dev->port_number, |
| 365 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); | 404 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); |
| 366 | 405 | ||
| 367 | if (result) { | 406 | if (result) { |
| @@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | |||
| 370 | return result; | 409 | return result; |
| 371 | } | 410 | } |
| 372 | 411 | ||
| 373 | dev->priv->stats.bytes_read += *bytes_read; | 412 | priv->stats.bytes_read += *bytes_read; |
| 374 | 413 | ||
| 375 | dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, | 414 | dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, |
| 376 | *bytes_read, bytes, dev->priv->stats.bytes_read); | 415 | *bytes_read, bytes, priv->stats.bytes_read); |
| 377 | 416 | ||
| 378 | return result; | 417 | return result; |
| 379 | } | 418 | } |
| 380 | 419 | ||
| 381 | /** | 420 | /** |
| 382 | * ps3_vuart_clear_rx_bytes - Discard bytes received. | 421 | * ps3_vuart_clear_rx_bytes - Discard bytes received. |
| 422 | * @dev: The struct ps3_system_bus_device instance. | ||
| 383 | * @bytes: Max byte count to discard, zero = all pending. | 423 | * @bytes: Max byte count to discard, zero = all pending. |
| 384 | * | 424 | * |
| 385 | * Used to clear pending rx interrupt source. Will not block. | 425 | * Used to clear pending rx interrupt source. Will not block. |
| 386 | */ | 426 | */ |
| 387 | 427 | ||
| 388 | void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, | 428 | void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev, |
| 389 | unsigned int bytes) | 429 | unsigned int bytes) |
| 390 | { | 430 | { |
| 391 | int result; | 431 | int result; |
| 432 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 392 | u64 bytes_waiting; | 433 | u64 bytes_waiting; |
| 393 | void* tmp; | 434 | void* tmp; |
| 394 | 435 | ||
| @@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, | |||
| 418 | 459 | ||
| 419 | /* Don't include these bytes in the stats. */ | 460 | /* Don't include these bytes in the stats. */ |
| 420 | 461 | ||
| 421 | dev->priv->stats.bytes_read -= bytes_waiting; | 462 | priv->stats.bytes_read -= bytes_waiting; |
| 422 | } | 463 | } |
| 464 | EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes); | ||
| 423 | 465 | ||
| 424 | /** | 466 | /** |
| 425 | * struct list_buffer - An element for a port device fifo buffer list. | 467 | * struct list_buffer - An element for a port device fifo buffer list. |
| @@ -435,6 +477,7 @@ struct list_buffer { | |||
| 435 | 477 | ||
| 436 | /** | 478 | /** |
| 437 | * ps3_vuart_write - the entry point for writing data to a port | 479 | * ps3_vuart_write - the entry point for writing data to a port |
| 480 | * @dev: The struct ps3_system_bus_device instance. | ||
| 438 | * | 481 | * |
| 439 | * If the port is idle on entry as much of the incoming data is written to | 482 | * If the port is idle on entry as much of the incoming data is written to |
| 440 | * the port as the port will accept. Otherwise a list buffer is created | 483 | * the port as the port will accept. Otherwise a list buffer is created |
| @@ -442,25 +485,26 @@ struct list_buffer { | |||
| 442 | * then enqueued for transmision via the transmit interrupt. | 485 | * then enqueued for transmision via the transmit interrupt. |
| 443 | */ | 486 | */ |
| 444 | 487 | ||
| 445 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | 488 | int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, |
| 446 | unsigned int bytes) | 489 | unsigned int bytes) |
| 447 | { | 490 | { |
| 448 | static unsigned long dbg_number; | 491 | static unsigned long dbg_number; |
| 449 | int result; | 492 | int result; |
| 493 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 450 | unsigned long flags; | 494 | unsigned long flags; |
| 451 | struct list_buffer *lb; | 495 | struct list_buffer *lb; |
| 452 | 496 | ||
| 453 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | 497 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, |
| 454 | bytes, bytes); | 498 | bytes, bytes); |
| 455 | 499 | ||
| 456 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); | 500 | spin_lock_irqsave(&priv->tx_list.lock, flags); |
| 457 | 501 | ||
| 458 | if (list_empty(&dev->priv->tx_list.head)) { | 502 | if (list_empty(&priv->tx_list.head)) { |
| 459 | unsigned long bytes_written; | 503 | unsigned long bytes_written; |
| 460 | 504 | ||
| 461 | result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); | 505 | result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); |
| 462 | 506 | ||
| 463 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); | 507 | spin_unlock_irqrestore(&priv->tx_list.lock, flags); |
| 464 | 508 | ||
| 465 | if (result) { | 509 | if (result) { |
| 466 | dev_dbg(&dev->core, | 510 | dev_dbg(&dev->core, |
| @@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | |||
| 478 | bytes -= bytes_written; | 522 | bytes -= bytes_written; |
| 479 | buf += bytes_written; | 523 | buf += bytes_written; |
| 480 | } else | 524 | } else |
| 481 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); | 525 | spin_unlock_irqrestore(&priv->tx_list.lock, flags); |
| 482 | 526 | ||
| 483 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); | 527 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); |
| 484 | 528 | ||
| @@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | |||
| 491 | lb->tail = lb->data + bytes; | 535 | lb->tail = lb->data + bytes; |
| 492 | lb->dbg_number = ++dbg_number; | 536 | lb->dbg_number = ++dbg_number; |
| 493 | 537 | ||
| 494 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); | 538 | spin_lock_irqsave(&priv->tx_list.lock, flags); |
| 495 | list_add_tail(&lb->link, &dev->priv->tx_list.head); | 539 | list_add_tail(&lb->link, &priv->tx_list.head); |
| 496 | ps3_vuart_enable_interrupt_tx(dev); | 540 | ps3_vuart_enable_interrupt_tx(dev); |
| 497 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); | 541 | spin_unlock_irqrestore(&priv->tx_list.lock, flags); |
| 498 | 542 | ||
| 499 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", | 543 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", |
| 500 | __func__, __LINE__, lb->dbg_number, bytes); | 544 | __func__, __LINE__, lb->dbg_number, bytes); |
| 501 | 545 | ||
| 502 | return 0; | 546 | return 0; |
| 503 | } | 547 | } |
| 548 | EXPORT_SYMBOL_GPL(ps3_vuart_write); | ||
| 549 | |||
| 550 | /** | ||
| 551 | * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list. | ||
| 552 | * @dev: The struct ps3_system_bus_device instance. | ||
| 553 | * @bytes_queued: Number of bytes queued to the buffer list. | ||
| 554 | * | ||
| 555 | * Must be called with priv->rx_list.lock held. | ||
| 556 | */ | ||
| 557 | |||
| 558 | static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev, | ||
| 559 | u64 *bytes_queued) | ||
| 560 | { | ||
| 561 | static unsigned long dbg_number; | ||
| 562 | int result; | ||
| 563 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 564 | struct list_buffer *lb; | ||
| 565 | u64 bytes; | ||
| 566 | |||
| 567 | *bytes_queued = 0; | ||
| 568 | |||
| 569 | result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); | ||
| 570 | BUG_ON(result); | ||
| 571 | |||
| 572 | if (result) | ||
| 573 | return -EIO; | ||
| 574 | |||
| 575 | if (!bytes) | ||
| 576 | return 0; | ||
| 577 | |||
| 578 | /* Add some extra space for recently arrived data. */ | ||
| 579 | |||
| 580 | bytes += 128; | ||
| 581 | |||
| 582 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); | ||
| 583 | |||
| 584 | if (!lb) | ||
| 585 | return -ENOMEM; | ||
| 586 | |||
| 587 | ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); | ||
| 588 | |||
| 589 | lb->head = lb->data; | ||
| 590 | lb->tail = lb->data + bytes; | ||
| 591 | lb->dbg_number = ++dbg_number; | ||
| 592 | |||
| 593 | list_add_tail(&lb->link, &priv->rx_list.head); | ||
| 594 | priv->rx_list.bytes_held += bytes; | ||
| 595 | |||
| 596 | dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n", | ||
| 597 | __func__, __LINE__, lb->dbg_number, bytes); | ||
| 598 | |||
| 599 | *bytes_queued = bytes; | ||
| 600 | |||
| 601 | return 0; | ||
| 602 | } | ||
| 504 | 603 | ||
| 505 | /** | 604 | /** |
| 506 | * ps3_vuart_read - the entry point for reading data from a port | 605 | * ps3_vuart_read - The entry point for reading data from a port. |
| 507 | * | 606 | * |
| 508 | * If enough bytes to satisfy the request are held in the buffer list those | 607 | * Queue data waiting at the port, and if enough bytes to satisfy the request |
| 509 | * bytes are dequeued and copied to the caller's buffer. Emptied list buffers | 608 | * are held in the buffer list those bytes are dequeued and copied to the |
| 510 | * are retiered. If the request cannot be statified by bytes held in the list | 609 | * caller's buffer. Emptied list buffers are retiered. If the request cannot |
| 511 | * buffers -EAGAIN is returned. | 610 | * be statified by bytes held in the list buffers -EAGAIN is returned. |
| 512 | */ | 611 | */ |
| 513 | 612 | ||
| 514 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | 613 | int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, |
| 515 | unsigned int bytes) | 614 | unsigned int bytes) |
| 516 | { | 615 | { |
| 616 | int result; | ||
| 617 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 517 | unsigned long flags; | 618 | unsigned long flags; |
| 518 | struct list_buffer *lb, *n; | 619 | struct list_buffer *lb, *n; |
| 519 | unsigned long bytes_read; | 620 | unsigned long bytes_read; |
| @@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | |||
| 521 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | 622 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, |
| 522 | bytes, bytes); | 623 | bytes, bytes); |
| 523 | 624 | ||
| 524 | spin_lock_irqsave(&dev->priv->rx_list.lock, flags); | 625 | spin_lock_irqsave(&priv->rx_list.lock, flags); |
| 525 | 626 | ||
| 526 | if (dev->priv->rx_list.bytes_held < bytes) { | 627 | /* Queue rx bytes here for polled reads. */ |
| 527 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); | 628 | |
| 528 | dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", | 629 | while (priv->rx_list.bytes_held < bytes) { |
| 529 | __func__, __LINE__, | 630 | u64 tmp; |
| 530 | bytes - dev->priv->rx_list.bytes_held); | 631 | |
| 531 | return -EAGAIN; | 632 | result = ps3_vuart_queue_rx_bytes(dev, &tmp); |
| 633 | if (result || !tmp) { | ||
| 634 | dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", | ||
| 635 | __func__, __LINE__, | ||
| 636 | bytes - priv->rx_list.bytes_held); | ||
| 637 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); | ||
| 638 | return -EAGAIN; | ||
| 639 | } | ||
| 532 | } | 640 | } |
| 533 | 641 | ||
| 534 | list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) { | 642 | list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) { |
| 535 | bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); | 643 | bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); |
| 536 | 644 | ||
| 537 | memcpy(buf, lb->head, bytes_read); | 645 | memcpy(buf, lb->head, bytes_read); |
| 538 | buf += bytes_read; | 646 | buf += bytes_read; |
| 539 | bytes -= bytes_read; | 647 | bytes -= bytes_read; |
| 540 | dev->priv->rx_list.bytes_held -= bytes_read; | 648 | priv->rx_list.bytes_held -= bytes_read; |
| 541 | 649 | ||
| 542 | if (bytes_read < lb->tail - lb->head) { | 650 | if (bytes_read < lb->tail - lb->head) { |
| 543 | lb->head += bytes_read; | 651 | lb->head += bytes_read; |
| 544 | dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " | 652 | dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " |
| 545 | "bytes\n", __func__, __LINE__, lb->dbg_number, | 653 | "bytes\n", __func__, __LINE__, lb->dbg_number, |
| 546 | bytes_read); | 654 | bytes_read); |
| 547 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); | 655 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 548 | return 0; | 656 | return 0; |
| 549 | } | 657 | } |
| 550 | 658 | ||
| @@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | |||
| 556 | kfree(lb); | 664 | kfree(lb); |
| 557 | } | 665 | } |
| 558 | 666 | ||
| 559 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); | 667 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 560 | return 0; | 668 | return 0; |
| 561 | } | 669 | } |
| 670 | EXPORT_SYMBOL_GPL(ps3_vuart_read); | ||
| 562 | 671 | ||
| 563 | int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, | 672 | /** |
| 564 | unsigned int bytes) | 673 | * ps3_vuart_work - Asynchronous read handler. |
| 674 | */ | ||
| 675 | |||
| 676 | static void ps3_vuart_work(struct work_struct *work) | ||
| 677 | { | ||
| 678 | struct ps3_system_bus_device *dev = | ||
| 679 | ps3_vuart_work_to_system_bus_dev(work); | ||
| 680 | struct ps3_vuart_port_driver *drv = | ||
| 681 | ps3_system_bus_dev_to_vuart_drv(dev); | ||
| 682 | |||
| 683 | BUG_ON(!drv); | ||
| 684 | drv->work(dev); | ||
| 685 | } | ||
| 686 | |||
| 687 | int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes) | ||
| 565 | { | 688 | { |
| 689 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 566 | unsigned long flags; | 690 | unsigned long flags; |
| 567 | 691 | ||
| 568 | if(dev->priv->work.trigger) { | 692 | if (priv->rx_list.work.trigger) { |
| 569 | dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n", | 693 | dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n", |
| 570 | __func__, __LINE__); | 694 | __func__, __LINE__); |
| 571 | return -EAGAIN; | 695 | return -EAGAIN; |
| @@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, | |||
| 573 | 697 | ||
| 574 | BUG_ON(!bytes); | 698 | BUG_ON(!bytes); |
| 575 | 699 | ||
| 576 | PREPARE_WORK(&dev->priv->work.work, func); | 700 | PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work); |
| 577 | 701 | ||
| 578 | spin_lock_irqsave(&dev->priv->work.lock, flags); | 702 | spin_lock_irqsave(&priv->rx_list.lock, flags); |
| 579 | if(dev->priv->rx_list.bytes_held >= bytes) { | 703 | if (priv->rx_list.bytes_held >= bytes) { |
| 580 | dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n", | 704 | dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n", |
| 581 | __func__, __LINE__, bytes); | 705 | __func__, __LINE__, bytes); |
| 582 | schedule_work(&dev->priv->work.work); | 706 | schedule_work(&priv->rx_list.work.work); |
| 583 | spin_unlock_irqrestore(&dev->priv->work.lock, flags); | 707 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 584 | return 0; | 708 | return 0; |
| 585 | } | 709 | } |
| 586 | 710 | ||
| 587 | dev->priv->work.trigger = bytes; | 711 | priv->rx_list.work.trigger = bytes; |
| 588 | spin_unlock_irqrestore(&dev->priv->work.lock, flags); | 712 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 589 | 713 | ||
| 590 | dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__, | 714 | dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__, |
| 591 | __LINE__, bytes, bytes); | 715 | __LINE__, bytes, bytes); |
| 592 | 716 | ||
| 593 | return 0; | 717 | return 0; |
| 594 | } | 718 | } |
| 719 | EXPORT_SYMBOL_GPL(ps3_vuart_read_async); | ||
| 595 | 720 | ||
| 596 | void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) | 721 | void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev) |
| 597 | { | 722 | { |
| 598 | dev->priv->work.trigger = 0; | 723 | to_port_priv(dev)->rx_list.work.trigger = 0; |
| 599 | } | 724 | } |
| 725 | EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async); | ||
| 600 | 726 | ||
| 601 | /** | 727 | /** |
| 602 | * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler | 728 | * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler |
| @@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) | |||
| 606 | * adjusts the final list buffer state for a partial write. | 732 | * adjusts the final list buffer state for a partial write. |
| 607 | */ | 733 | */ |
| 608 | 734 | ||
| 609 | static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | 735 | static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev) |
| 610 | { | 736 | { |
| 611 | int result = 0; | 737 | int result = 0; |
| 738 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 612 | unsigned long flags; | 739 | unsigned long flags; |
| 613 | struct list_buffer *lb, *n; | 740 | struct list_buffer *lb, *n; |
| 614 | unsigned long bytes_total = 0; | 741 | unsigned long bytes_total = 0; |
| 615 | 742 | ||
| 616 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 743 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 617 | 744 | ||
| 618 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); | 745 | spin_lock_irqsave(&priv->tx_list.lock, flags); |
| 619 | 746 | ||
| 620 | list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) { | 747 | list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) { |
| 621 | 748 | ||
| 622 | unsigned long bytes_written; | 749 | unsigned long bytes_written; |
| 623 | 750 | ||
| @@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | |||
| 651 | 778 | ||
| 652 | ps3_vuart_disable_interrupt_tx(dev); | 779 | ps3_vuart_disable_interrupt_tx(dev); |
| 653 | port_full: | 780 | port_full: |
| 654 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); | 781 | spin_unlock_irqrestore(&priv->tx_list.lock, flags); |
| 655 | dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", | 782 | dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", |
| 656 | __func__, __LINE__, bytes_total); | 783 | __func__, __LINE__, bytes_total); |
| 657 | return result; | 784 | return result; |
| @@ -665,60 +792,37 @@ port_full: | |||
| 665 | * buffer list. Buffer list data is dequeued via ps3_vuart_read. | 792 | * buffer list. Buffer list data is dequeued via ps3_vuart_read. |
| 666 | */ | 793 | */ |
| 667 | 794 | ||
| 668 | static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) | 795 | static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev) |
| 669 | { | 796 | { |
| 670 | static unsigned long dbg_number; | 797 | int result; |
| 671 | int result = 0; | 798 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); |
| 672 | unsigned long flags; | 799 | unsigned long flags; |
| 673 | struct list_buffer *lb; | 800 | u64 bytes; |
| 674 | unsigned long bytes; | ||
| 675 | 801 | ||
| 676 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 802 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 677 | 803 | ||
| 678 | result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); | 804 | spin_lock_irqsave(&priv->rx_list.lock, flags); |
| 679 | 805 | result = ps3_vuart_queue_rx_bytes(dev, &bytes); | |
| 680 | if (result) | ||
| 681 | return -EIO; | ||
| 682 | |||
| 683 | BUG_ON(!bytes); | ||
| 684 | |||
| 685 | /* Add some extra space for recently arrived data. */ | ||
| 686 | |||
| 687 | bytes += 128; | ||
| 688 | |||
| 689 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); | ||
| 690 | 806 | ||
| 691 | if (!lb) | 807 | if (result) { |
| 692 | return -ENOMEM; | 808 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 693 | 809 | return result; | |
| 694 | ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); | 810 | } |
| 695 | |||
| 696 | lb->head = lb->data; | ||
| 697 | lb->tail = lb->data + bytes; | ||
| 698 | lb->dbg_number = ++dbg_number; | ||
| 699 | |||
| 700 | spin_lock_irqsave(&dev->priv->rx_list.lock, flags); | ||
| 701 | list_add_tail(&lb->link, &dev->priv->rx_list.head); | ||
| 702 | dev->priv->rx_list.bytes_held += bytes; | ||
| 703 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); | ||
| 704 | |||
| 705 | dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n", | ||
| 706 | __func__, __LINE__, lb->dbg_number, bytes); | ||
| 707 | 811 | ||
| 708 | spin_lock_irqsave(&dev->priv->work.lock, flags); | 812 | if (priv->rx_list.work.trigger && priv->rx_list.bytes_held |
| 709 | if(dev->priv->work.trigger | 813 | >= priv->rx_list.work.trigger) { |
| 710 | && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) { | ||
| 711 | dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n", | 814 | dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n", |
| 712 | __func__, __LINE__, dev->priv->work.trigger); | 815 | __func__, __LINE__, priv->rx_list.work.trigger); |
| 713 | dev->priv->work.trigger = 0; | 816 | priv->rx_list.work.trigger = 0; |
| 714 | schedule_work(&dev->priv->work.work); | 817 | schedule_work(&priv->rx_list.work.work); |
| 715 | } | 818 | } |
| 716 | spin_unlock_irqrestore(&dev->priv->work.lock, flags); | 819 | |
| 717 | return 0; | 820 | spin_unlock_irqrestore(&priv->rx_list.lock, flags); |
| 821 | return result; | ||
| 718 | } | 822 | } |
| 719 | 823 | ||
| 720 | static int ps3_vuart_handle_interrupt_disconnect( | 824 | static int ps3_vuart_handle_interrupt_disconnect( |
| 721 | struct ps3_vuart_port_device *dev) | 825 | struct ps3_system_bus_device *dev) |
| 722 | { | 826 | { |
| 723 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 827 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 724 | BUG_ON("no support"); | 828 | BUG_ON("no support"); |
| @@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_disconnect( | |||
| 733 | * stage handler after one iteration. | 837 | * stage handler after one iteration. |
| 734 | */ | 838 | */ |
| 735 | 839 | ||
| 736 | static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | 840 | static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev) |
| 737 | { | 841 | { |
| 738 | int result; | 842 | int result; |
| 843 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 739 | unsigned long status; | 844 | unsigned long status; |
| 740 | 845 | ||
| 741 | result = ps3_vuart_get_interrupt_status(dev, &status); | 846 | result = ps3_vuart_get_interrupt_status(dev, &status); |
| @@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | |||
| 747 | status); | 852 | status); |
| 748 | 853 | ||
| 749 | if (status & INTERRUPT_MASK_DISCONNECT) { | 854 | if (status & INTERRUPT_MASK_DISCONNECT) { |
| 750 | dev->priv->stats.disconnect_interrupts++; | 855 | priv->stats.disconnect_interrupts++; |
| 751 | result = ps3_vuart_handle_interrupt_disconnect(dev); | 856 | result = ps3_vuart_handle_interrupt_disconnect(dev); |
| 752 | if (result) | 857 | if (result) |
| 753 | ps3_vuart_disable_interrupt_disconnect(dev); | 858 | ps3_vuart_disable_interrupt_disconnect(dev); |
| 754 | } | 859 | } |
| 755 | 860 | ||
| 756 | if (status & INTERRUPT_MASK_TX) { | 861 | if (status & INTERRUPT_MASK_TX) { |
| 757 | dev->priv->stats.tx_interrupts++; | 862 | priv->stats.tx_interrupts++; |
| 758 | result = ps3_vuart_handle_interrupt_tx(dev); | 863 | result = ps3_vuart_handle_interrupt_tx(dev); |
| 759 | if (result) | 864 | if (result) |
| 760 | ps3_vuart_disable_interrupt_tx(dev); | 865 | ps3_vuart_disable_interrupt_tx(dev); |
| 761 | } | 866 | } |
| 762 | 867 | ||
| 763 | if (status & INTERRUPT_MASK_RX) { | 868 | if (status & INTERRUPT_MASK_RX) { |
| 764 | dev->priv->stats.rx_interrupts++; | 869 | priv->stats.rx_interrupts++; |
| 765 | result = ps3_vuart_handle_interrupt_rx(dev); | 870 | result = ps3_vuart_handle_interrupt_rx(dev); |
| 766 | if (result) | 871 | if (result) |
| 767 | ps3_vuart_disable_interrupt_rx(dev); | 872 | ps3_vuart_disable_interrupt_rx(dev); |
| @@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | |||
| 771 | } | 876 | } |
| 772 | 877 | ||
| 773 | struct vuart_bus_priv { | 878 | struct vuart_bus_priv { |
| 774 | const struct ports_bmp bmp; | 879 | struct ports_bmp *bmp; |
| 775 | unsigned int virq; | 880 | unsigned int virq; |
| 776 | struct semaphore probe_mutex; | 881 | struct semaphore probe_mutex; |
| 777 | int use_count; | 882 | int use_count; |
| 778 | struct ps3_vuart_port_device *devices[PORT_COUNT]; | 883 | struct ps3_system_bus_device *devices[PORT_COUNT]; |
| 779 | } static vuart_bus_priv; | 884 | } static vuart_bus_priv; |
| 780 | 885 | ||
| 781 | /** | 886 | /** |
| @@ -788,17 +893,16 @@ struct vuart_bus_priv { | |||
| 788 | 893 | ||
| 789 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) | 894 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) |
| 790 | { | 895 | { |
| 791 | struct vuart_bus_priv *bus_priv; | 896 | struct vuart_bus_priv *bus_priv = _private; |
| 792 | 897 | ||
| 793 | BUG_ON(!_private); | 898 | BUG_ON(!bus_priv); |
| 794 | bus_priv = (struct vuart_bus_priv *)_private; | ||
| 795 | 899 | ||
| 796 | while (1) { | 900 | while (1) { |
| 797 | unsigned int port; | 901 | unsigned int port; |
| 798 | 902 | ||
| 799 | dump_ports_bmp(&bus_priv->bmp); | 903 | dump_ports_bmp(bus_priv->bmp); |
| 800 | 904 | ||
| 801 | port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status); | 905 | port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status); |
| 802 | 906 | ||
| 803 | if (port == BITS_PER_LONG) | 907 | if (port == BITS_PER_LONG) |
| 804 | break; | 908 | break; |
| @@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) | |||
| 812 | return IRQ_HANDLED; | 916 | return IRQ_HANDLED; |
| 813 | } | 917 | } |
| 814 | 918 | ||
| 815 | static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) | 919 | static int ps3_vuart_bus_interrupt_get(void) |
| 816 | { | 920 | { |
| 817 | int result; | 921 | int result; |
| 818 | struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv); | ||
| 819 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
| 820 | 922 | ||
| 821 | result = dev->match_id == drv->match_id; | 923 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
| 924 | |||
| 925 | vuart_bus_priv.use_count++; | ||
| 926 | |||
| 927 | BUG_ON(vuart_bus_priv.use_count > 2); | ||
| 928 | |||
| 929 | if (vuart_bus_priv.use_count != 1) { | ||
| 930 | return 0; | ||
| 931 | } | ||
| 932 | |||
| 933 | BUG_ON(vuart_bus_priv.bmp); | ||
| 934 | |||
| 935 | vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL); | ||
| 936 | |||
| 937 | if (!vuart_bus_priv.bmp) { | ||
| 938 | pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__); | ||
| 939 | result = -ENOMEM; | ||
| 940 | goto fail_bmp_malloc; | ||
| 941 | } | ||
| 942 | |||
| 943 | result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp, | ||
| 944 | &vuart_bus_priv.virq); | ||
| 945 | |||
| 946 | if (result) { | ||
| 947 | pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n", | ||
| 948 | __func__, __LINE__, result); | ||
| 949 | result = -EPERM; | ||
| 950 | goto fail_alloc_irq; | ||
| 951 | } | ||
| 952 | |||
| 953 | result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, | ||
| 954 | IRQF_DISABLED, "vuart", &vuart_bus_priv); | ||
| 822 | 955 | ||
| 823 | dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, | 956 | if (result) { |
| 824 | __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, | 957 | pr_debug("%s:%d: request_irq failed (%d)\n", |
| 825 | drv->core.name, (result ? "match" : "miss")); | 958 | __func__, __LINE__, result); |
| 959 | goto fail_request_irq; | ||
| 960 | } | ||
| 826 | 961 | ||
| 962 | pr_debug(" <- %s:%d: ok\n", __func__, __LINE__); | ||
| 827 | return result; | 963 | return result; |
| 964 | |||
| 965 | fail_request_irq: | ||
| 966 | ps3_vuart_irq_destroy(vuart_bus_priv.virq); | ||
| 967 | vuart_bus_priv.virq = NO_IRQ; | ||
| 968 | fail_alloc_irq: | ||
| 969 | kfree(vuart_bus_priv.bmp); | ||
| 970 | vuart_bus_priv.bmp = NULL; | ||
| 971 | fail_bmp_malloc: | ||
| 972 | vuart_bus_priv.use_count--; | ||
| 973 | pr_debug(" <- %s:%d: failed\n", __func__, __LINE__); | ||
| 974 | return result; | ||
| 975 | } | ||
| 976 | |||
| 977 | static int ps3_vuart_bus_interrupt_put(void) | ||
| 978 | { | ||
| 979 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
| 980 | |||
| 981 | vuart_bus_priv.use_count--; | ||
| 982 | |||
| 983 | BUG_ON(vuart_bus_priv.use_count < 0); | ||
| 984 | |||
| 985 | if (vuart_bus_priv.use_count != 0) | ||
| 986 | return 0; | ||
| 987 | |||
| 988 | free_irq(vuart_bus_priv.virq, &vuart_bus_priv); | ||
| 989 | |||
| 990 | ps3_vuart_irq_destroy(vuart_bus_priv.virq); | ||
| 991 | vuart_bus_priv.virq = NO_IRQ; | ||
| 992 | |||
| 993 | kfree(vuart_bus_priv.bmp); | ||
| 994 | vuart_bus_priv.bmp = NULL; | ||
| 995 | |||
| 996 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
| 997 | return 0; | ||
| 828 | } | 998 | } |
| 829 | 999 | ||
| 830 | static int ps3_vuart_probe(struct device *_dev) | 1000 | static int ps3_vuart_probe(struct ps3_system_bus_device *dev) |
| 831 | { | 1001 | { |
| 832 | int result; | 1002 | int result; |
| 833 | unsigned int port_number; | 1003 | struct ps3_vuart_port_driver *drv; |
| 834 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | 1004 | struct ps3_vuart_port_priv *priv = NULL; |
| 835 | struct ps3_vuart_port_driver *drv = | ||
| 836 | to_ps3_vuart_port_driver(_dev->driver); | ||
| 837 | 1005 | ||
| 838 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 1006 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 839 | 1007 | ||
| 1008 | drv = ps3_system_bus_dev_to_vuart_drv(dev); | ||
| 1009 | |||
| 1010 | dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, | ||
| 1011 | drv->core.core.name); | ||
| 1012 | |||
| 840 | BUG_ON(!drv); | 1013 | BUG_ON(!drv); |
| 841 | 1014 | ||
| 842 | down(&vuart_bus_priv.probe_mutex); | 1015 | if (dev->port_number >= PORT_COUNT) { |
| 1016 | BUG(); | ||
| 1017 | return -EINVAL; | ||
| 1018 | } | ||
| 843 | 1019 | ||
| 844 | /* Setup vuart_bus_priv.devices[]. */ | 1020 | down(&vuart_bus_priv.probe_mutex); |
| 845 | 1021 | ||
| 846 | result = ps3_vuart_match_id_to_port(dev->match_id, | 1022 | result = ps3_vuart_bus_interrupt_get(); |
| 847 | &port_number); | ||
| 848 | 1023 | ||
| 849 | if (result) { | 1024 | if (result) |
| 850 | dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", | 1025 | goto fail_setup_interrupt; |
| 851 | __func__, __LINE__, dev->match_id); | ||
| 852 | result = -EINVAL; | ||
| 853 | goto fail_match; | ||
| 854 | } | ||
| 855 | 1026 | ||
| 856 | if (vuart_bus_priv.devices[port_number]) { | 1027 | if (vuart_bus_priv.devices[dev->port_number]) { |
| 857 | dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, | 1028 | dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, |
| 858 | __LINE__, port_number); | 1029 | __LINE__, dev->port_number); |
| 859 | result = -EBUSY; | 1030 | result = -EBUSY; |
| 860 | goto fail_match; | 1031 | goto fail_busy; |
| 861 | } | 1032 | } |
| 862 | 1033 | ||
| 863 | vuart_bus_priv.devices[port_number] = dev; | 1034 | vuart_bus_priv.devices[dev->port_number] = dev; |
| 864 | 1035 | ||
| 865 | /* Setup dev->priv. */ | 1036 | /* Setup dev->driver_priv. */ |
| 866 | 1037 | ||
| 867 | dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL); | 1038 | dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv), |
| 1039 | GFP_KERNEL); | ||
| 868 | 1040 | ||
| 869 | if (!dev->priv) { | 1041 | if (!dev->driver_priv) { |
| 870 | result = -ENOMEM; | 1042 | result = -ENOMEM; |
| 871 | goto fail_alloc; | 1043 | goto fail_dev_malloc; |
| 872 | } | 1044 | } |
| 873 | 1045 | ||
| 874 | dev->priv->port_number = port_number; | 1046 | priv = to_port_priv(dev); |
| 875 | |||
| 876 | INIT_LIST_HEAD(&dev->priv->tx_list.head); | ||
| 877 | spin_lock_init(&dev->priv->tx_list.lock); | ||
| 878 | 1047 | ||
| 879 | INIT_LIST_HEAD(&dev->priv->rx_list.head); | 1048 | INIT_LIST_HEAD(&priv->tx_list.head); |
| 880 | spin_lock_init(&dev->priv->rx_list.lock); | 1049 | spin_lock_init(&priv->tx_list.lock); |
| 881 | 1050 | ||
| 882 | INIT_WORK(&dev->priv->work.work, NULL); | 1051 | INIT_LIST_HEAD(&priv->rx_list.head); |
| 883 | spin_lock_init(&dev->priv->work.lock); | 1052 | spin_lock_init(&priv->rx_list.lock); |
| 884 | dev->priv->work.trigger = 0; | ||
| 885 | dev->priv->work.dev = dev; | ||
| 886 | 1053 | ||
| 887 | if (++vuart_bus_priv.use_count == 1) { | 1054 | INIT_WORK(&priv->rx_list.work.work, NULL); |
| 888 | 1055 | priv->rx_list.work.trigger = 0; | |
| 889 | result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, | 1056 | priv->rx_list.work.dev = dev; |
| 890 | (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq); | ||
| 891 | |||
| 892 | if (result) { | ||
| 893 | dev_dbg(&dev->core, | ||
| 894 | "%s:%d: ps3_vuart_irq_setup failed (%d)\n", | ||
| 895 | __func__, __LINE__, result); | ||
| 896 | result = -EPERM; | ||
| 897 | goto fail_alloc_irq; | ||
| 898 | } | ||
| 899 | |||
| 900 | result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, | ||
| 901 | IRQF_DISABLED, "vuart", &vuart_bus_priv); | ||
| 902 | |||
| 903 | if (result) { | ||
| 904 | dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", | ||
| 905 | __func__, __LINE__, result); | ||
| 906 | goto fail_request_irq; | ||
| 907 | } | ||
| 908 | } | ||
| 909 | 1057 | ||
| 910 | /* clear stale pending interrupts */ | 1058 | /* clear stale pending interrupts */ |
| 911 | 1059 | ||
| @@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device *_dev) | |||
| 936 | 1084 | ||
| 937 | fail_probe: | 1085 | fail_probe: |
| 938 | ps3_vuart_set_interrupt_mask(dev, 0); | 1086 | ps3_vuart_set_interrupt_mask(dev, 0); |
| 939 | fail_request_irq: | 1087 | kfree(dev->driver_priv); |
| 940 | ps3_vuart_irq_destroy(vuart_bus_priv.virq); | 1088 | dev->driver_priv = NULL; |
| 941 | vuart_bus_priv.virq = NO_IRQ; | 1089 | fail_dev_malloc: |
| 942 | fail_alloc_irq: | 1090 | vuart_bus_priv.devices[dev->port_number] = NULL; |
| 943 | --vuart_bus_priv.use_count; | 1091 | fail_busy: |
| 944 | kfree(dev->priv); | 1092 | ps3_vuart_bus_interrupt_put(); |
| 945 | dev->priv = NULL; | 1093 | fail_setup_interrupt: |
| 946 | fail_alloc: | ||
| 947 | vuart_bus_priv.devices[port_number] = NULL; | ||
| 948 | fail_match: | ||
| 949 | up(&vuart_bus_priv.probe_mutex); | 1094 | up(&vuart_bus_priv.probe_mutex); |
| 950 | dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); | 1095 | dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__); |
| 951 | return result; | 1096 | return result; |
| 952 | } | 1097 | } |
| 953 | 1098 | ||
| 954 | static int ps3_vuart_remove(struct device *_dev) | 1099 | /** |
| 1100 | * ps3_vuart_cleanup - common cleanup helper. | ||
| 1101 | * @dev: The struct ps3_system_bus_device instance. | ||
| 1102 | * | ||
| 1103 | * Cleans interrupts and HV resources. Must be called with | ||
| 1104 | * vuart_bus_priv.probe_mutex held. Used by ps3_vuart_remove and | ||
| 1105 | * ps3_vuart_shutdown. After this call, polled reading will still work. | ||
| 1106 | */ | ||
| 1107 | |||
| 1108 | static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev) | ||
| 955 | { | 1109 | { |
| 956 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | 1110 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
| 957 | struct ps3_vuart_port_driver *drv = | 1111 | |
| 958 | to_ps3_vuart_port_driver(_dev->driver); | 1112 | ps3_vuart_cancel_async(dev); |
| 1113 | ps3_vuart_set_interrupt_mask(dev, 0); | ||
| 1114 | ps3_vuart_bus_interrupt_put(); | ||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /** | ||
| 1119 | * ps3_vuart_remove - Completely clean the device instance. | ||
| 1120 | * @dev: The struct ps3_system_bus_device instance. | ||
| 1121 | * | ||
| 1122 | * Cleans all memory, interrupts and HV resources. After this call the | ||
| 1123 | * device can no longer be used. | ||
| 1124 | */ | ||
| 1125 | |||
| 1126 | static int ps3_vuart_remove(struct ps3_system_bus_device *dev) | ||
| 1127 | { | ||
| 1128 | struct ps3_vuart_port_priv *priv = to_port_priv(dev); | ||
| 1129 | struct ps3_vuart_port_driver *drv; | ||
| 1130 | |||
| 1131 | BUG_ON(!dev); | ||
| 959 | 1132 | ||
| 960 | down(&vuart_bus_priv.probe_mutex); | 1133 | down(&vuart_bus_priv.probe_mutex); |
| 961 | 1134 | ||
| 962 | dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, | 1135 | dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, |
| 963 | dev->core.bus_id); | 1136 | dev->match_id); |
| 964 | 1137 | ||
| 965 | BUG_ON(vuart_bus_priv.use_count < 1); | 1138 | if (!dev->core.driver) { |
| 1139 | dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, | ||
| 1140 | __LINE__); | ||
| 1141 | up(&vuart_bus_priv.probe_mutex); | ||
| 1142 | return 0; | ||
| 1143 | } | ||
| 966 | 1144 | ||
| 967 | if (drv->remove) | 1145 | drv = ps3_system_bus_dev_to_vuart_drv(dev); |
| 968 | drv->remove(dev); | ||
| 969 | else | ||
| 970 | dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, | ||
| 971 | __LINE__, dev->core.bus_id); | ||
| 972 | 1146 | ||
| 973 | vuart_bus_priv.devices[dev->priv->port_number] = NULL; | 1147 | BUG_ON(!drv); |
| 974 | 1148 | ||
| 975 | if (--vuart_bus_priv.use_count == 0) { | 1149 | if (drv->remove) { |
| 1150 | drv->remove(dev); | ||
| 1151 | } else { | ||
| 1152 | dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__, | ||
| 1153 | __LINE__); | ||
| 976 | BUG(); | 1154 | BUG(); |
| 977 | free_irq(vuart_bus_priv.virq, &vuart_bus_priv); | ||
| 978 | ps3_vuart_irq_destroy(vuart_bus_priv.virq); | ||
| 979 | vuart_bus_priv.virq = NO_IRQ; | ||
| 980 | } | 1155 | } |
| 981 | 1156 | ||
| 982 | kfree(dev->priv); | 1157 | ps3_vuart_cleanup(dev); |
| 983 | dev->priv = NULL; | 1158 | |
| 1159 | vuart_bus_priv.devices[dev->port_number] = NULL; | ||
| 1160 | kfree(priv); | ||
| 1161 | priv = NULL; | ||
| 984 | 1162 | ||
| 1163 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
| 985 | up(&vuart_bus_priv.probe_mutex); | 1164 | up(&vuart_bus_priv.probe_mutex); |
| 986 | return 0; | 1165 | return 0; |
| 987 | } | 1166 | } |
| 988 | 1167 | ||
| 989 | static void ps3_vuart_shutdown(struct device *_dev) | ||
| 990 | { | ||
| 991 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
| 992 | struct ps3_vuart_port_driver *drv = | ||
| 993 | to_ps3_vuart_port_driver(_dev->driver); | ||
| 994 | |||
| 995 | dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, | ||
| 996 | dev->core.bus_id); | ||
| 997 | |||
| 998 | if (drv->shutdown) | ||
| 999 | drv->shutdown(dev); | ||
| 1000 | else | ||
| 1001 | dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__, | ||
| 1002 | __LINE__, dev->core.bus_id); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /** | 1168 | /** |
| 1006 | * ps3_vuart_bus - The vuart bus instance. | 1169 | * ps3_vuart_shutdown - Cleans interrupts and HV resources. |
| 1170 | * @dev: The struct ps3_system_bus_device instance. | ||
| 1007 | * | 1171 | * |
| 1008 | * The vuart is managed as a bus that port devices connect to. | 1172 | * Cleans interrupts and HV resources. After this call the |
| 1173 | * device can still be used in polling mode. This behavior required | ||
| 1174 | * by sys-manager to be able to complete the device power operation | ||
| 1175 | * sequence. | ||
| 1009 | */ | 1176 | */ |
| 1010 | 1177 | ||
| 1011 | struct bus_type ps3_vuart_bus = { | 1178 | static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev) |
| 1012 | .name = "ps3_vuart", | ||
| 1013 | .match = ps3_vuart_match, | ||
| 1014 | .probe = ps3_vuart_probe, | ||
| 1015 | .remove = ps3_vuart_remove, | ||
| 1016 | .shutdown = ps3_vuart_shutdown, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | int __init ps3_vuart_bus_init(void) | ||
| 1020 | { | 1179 | { |
| 1021 | int result; | 1180 | struct ps3_vuart_port_driver *drv; |
| 1022 | 1181 | ||
| 1023 | pr_debug("%s:%d:\n", __func__, __LINE__); | 1182 | BUG_ON(!dev); |
| 1024 | 1183 | ||
| 1025 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | 1184 | down(&vuart_bus_priv.probe_mutex); |
| 1026 | return -ENODEV; | ||
| 1027 | 1185 | ||
| 1028 | init_MUTEX(&vuart_bus_priv.probe_mutex); | 1186 | dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, |
| 1029 | result = bus_register(&ps3_vuart_bus); | 1187 | dev->match_id); |
| 1030 | BUG_ON(result); | ||
| 1031 | 1188 | ||
| 1032 | return result; | 1189 | if (!dev->core.driver) { |
| 1033 | } | 1190 | dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, |
| 1191 | __LINE__); | ||
| 1192 | up(&vuart_bus_priv.probe_mutex); | ||
| 1193 | return 0; | ||
| 1194 | } | ||
| 1034 | 1195 | ||
| 1035 | void __exit ps3_vuart_bus_exit(void) | 1196 | drv = ps3_system_bus_dev_to_vuart_drv(dev); |
| 1036 | { | ||
| 1037 | pr_debug("%s:%d:\n", __func__, __LINE__); | ||
| 1038 | bus_unregister(&ps3_vuart_bus); | ||
| 1039 | } | ||
| 1040 | 1197 | ||
| 1041 | core_initcall(ps3_vuart_bus_init); | 1198 | BUG_ON(!drv); |
| 1042 | module_exit(ps3_vuart_bus_exit); | ||
| 1043 | 1199 | ||
| 1044 | /** | 1200 | if (drv->shutdown) |
| 1045 | * ps3_vuart_port_release_device - Remove a vuart port device. | 1201 | drv->shutdown(dev); |
| 1046 | */ | 1202 | else if (drv->remove) { |
| 1203 | dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n", | ||
| 1204 | __func__, __LINE__); | ||
| 1205 | drv->remove(dev); | ||
| 1206 | } else { | ||
| 1207 | dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__, | ||
| 1208 | __LINE__); | ||
| 1209 | BUG(); | ||
| 1210 | } | ||
| 1047 | 1211 | ||
| 1048 | static void ps3_vuart_port_release_device(struct device *_dev) | 1212 | ps3_vuart_cleanup(dev); |
| 1049 | { | ||
| 1050 | #if defined(DEBUG) | ||
| 1051 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
| 1052 | 1213 | ||
| 1053 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 1214 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
| 1054 | 1215 | ||
| 1055 | BUG_ON(dev->priv && "forgot to free"); | 1216 | up(&vuart_bus_priv.probe_mutex); |
| 1056 | memset(&dev->core, 0, sizeof(dev->core)); | 1217 | return 0; |
| 1057 | #endif | ||
| 1058 | } | 1218 | } |
| 1059 | 1219 | ||
| 1060 | /** | 1220 | static int __init ps3_vuart_bus_init(void) |
| 1061 | * ps3_vuart_port_device_register - Add a vuart port device. | ||
| 1062 | */ | ||
| 1063 | |||
| 1064 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) | ||
| 1065 | { | 1221 | { |
| 1066 | static unsigned int dev_count = 1; | 1222 | pr_debug("%s:%d:\n", __func__, __LINE__); |
| 1067 | |||
| 1068 | BUG_ON(dev->priv && "forgot to free"); | ||
| 1069 | 1223 | ||
| 1070 | dev->core.parent = NULL; | 1224 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) |
| 1071 | dev->core.bus = &ps3_vuart_bus; | 1225 | return -ENODEV; |
| 1072 | dev->core.release = ps3_vuart_port_release_device; | ||
| 1073 | 1226 | ||
| 1074 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", | 1227 | init_MUTEX(&vuart_bus_priv.probe_mutex); |
| 1075 | dev_count++); | ||
| 1076 | 1228 | ||
| 1077 | dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); | 1229 | return 0; |
| 1230 | } | ||
| 1078 | 1231 | ||
| 1079 | return device_register(&dev->core); | 1232 | static void __exit ps3_vuart_bus_exit(void) |
| 1233 | { | ||
| 1234 | pr_debug("%s:%d:\n", __func__, __LINE__); | ||
| 1080 | } | 1235 | } |
| 1081 | 1236 | ||
| 1082 | EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); | 1237 | core_initcall(ps3_vuart_bus_init); |
| 1238 | module_exit(ps3_vuart_bus_exit); | ||
| 1083 | 1239 | ||
| 1084 | /** | 1240 | /** |
| 1085 | * ps3_vuart_port_driver_register - Add a vuart port device driver. | 1241 | * ps3_vuart_port_driver_register - Add a vuart port device driver. |
| @@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) | |||
| 1089 | { | 1245 | { |
| 1090 | int result; | 1246 | int result; |
| 1091 | 1247 | ||
| 1092 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); | 1248 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name); |
| 1093 | drv->core.bus = &ps3_vuart_bus; | 1249 | |
| 1094 | result = driver_register(&drv->core); | 1250 | BUG_ON(!drv->core.match_id); |
| 1251 | BUG_ON(!drv->core.core.name); | ||
| 1252 | |||
| 1253 | drv->core.probe = ps3_vuart_probe; | ||
| 1254 | drv->core.remove = ps3_vuart_remove; | ||
| 1255 | drv->core.shutdown = ps3_vuart_shutdown; | ||
| 1256 | |||
| 1257 | result = ps3_system_bus_driver_register(&drv->core); | ||
| 1095 | return result; | 1258 | return result; |
| 1096 | } | 1259 | } |
| 1097 | |||
| 1098 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); | 1260 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); |
| 1099 | 1261 | ||
| 1100 | /** | 1262 | /** |
| @@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); | |||
| 1103 | 1265 | ||
| 1104 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) | 1266 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) |
| 1105 | { | 1267 | { |
| 1106 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); | 1268 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name); |
| 1107 | driver_unregister(&drv->core); | 1269 | ps3_system_bus_driver_unregister(&drv->core); |
| 1108 | } | 1270 | } |
| 1109 | |||
| 1110 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); | 1271 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); |
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h index 1be992d568c8..eb7f6d94a890 100644 --- a/drivers/ps3/vuart.h +++ b/drivers/ps3/vuart.h | |||
| @@ -34,29 +34,7 @@ struct ps3_vuart_stats { | |||
| 34 | struct ps3_vuart_work { | 34 | struct ps3_vuart_work { |
| 35 | struct work_struct work; | 35 | struct work_struct work; |
| 36 | unsigned long trigger; | 36 | unsigned long trigger; |
| 37 | spinlock_t lock; | 37 | struct ps3_system_bus_device *dev; /* to convert work to device */ |
| 38 | struct ps3_vuart_port_device* dev; /* to convert work to device */ | ||
| 39 | }; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct ps3_vuart_port_priv - private vuart device data. | ||
| 43 | */ | ||
| 44 | |||
| 45 | struct ps3_vuart_port_priv { | ||
| 46 | unsigned int port_number; | ||
| 47 | u64 interrupt_mask; | ||
| 48 | |||
| 49 | struct { | ||
| 50 | spinlock_t lock; | ||
| 51 | struct list_head head; | ||
| 52 | } tx_list; | ||
| 53 | struct { | ||
| 54 | unsigned long bytes_held; | ||
| 55 | spinlock_t lock; | ||
| 56 | struct list_head head; | ||
| 57 | } rx_list; | ||
| 58 | struct ps3_vuart_stats stats; | ||
| 59 | struct ps3_vuart_work work; | ||
| 60 | }; | 38 | }; |
| 61 | 39 | ||
| 62 | /** | 40 | /** |
| @@ -64,32 +42,30 @@ struct ps3_vuart_port_priv { | |||
| 64 | */ | 42 | */ |
| 65 | 43 | ||
| 66 | struct ps3_vuart_port_driver { | 44 | struct ps3_vuart_port_driver { |
| 67 | enum ps3_match_id match_id; | 45 | struct ps3_system_bus_driver core; |
| 68 | struct device_driver core; | 46 | int (*probe)(struct ps3_system_bus_device *); |
| 69 | int (*probe)(struct ps3_vuart_port_device *); | 47 | int (*remove)(struct ps3_system_bus_device *); |
| 70 | int (*remove)(struct ps3_vuart_port_device *); | 48 | void (*shutdown)(struct ps3_system_bus_device *); |
| 71 | void (*shutdown)(struct ps3_vuart_port_device *); | 49 | void (*work)(struct ps3_system_bus_device *); |
| 72 | int (*tx_event)(struct ps3_vuart_port_device *dev); | 50 | /* int (*tx_event)(struct ps3_system_bus_device *dev); */ |
| 73 | int (*rx_event)(struct ps3_vuart_port_device *dev); | 51 | /* int (*rx_event)(struct ps3_system_bus_device *dev); */ |
| 74 | int (*disconnect_event)(struct ps3_vuart_port_device *dev); | 52 | /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */ |
| 75 | /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ | 53 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ |
| 76 | /* int (*resume)(struct ps3_vuart_port_device *); */ | 54 | /* int (*resume)(struct ps3_system_bus_device *); */ |
| 77 | }; | 55 | }; |
| 78 | 56 | ||
| 79 | int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); | 57 | int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); |
| 80 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); | 58 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); |
| 81 | 59 | ||
| 82 | static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( | 60 | static inline struct ps3_vuart_port_driver * |
| 83 | struct device_driver *_drv) | 61 | ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev) |
| 84 | { | ||
| 85 | return container_of(_drv, struct ps3_vuart_port_driver, core); | ||
| 86 | } | ||
| 87 | static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device( | ||
| 88 | struct device *_dev) | ||
| 89 | { | 62 | { |
| 90 | return container_of(_dev, struct ps3_vuart_port_device, core); | 63 | struct ps3_system_bus_driver *sbd = |
| 64 | ps3_system_bus_dev_to_system_bus_drv(_dev); | ||
| 65 | BUG_ON(!sbd); | ||
| 66 | return container_of(sbd, struct ps3_vuart_port_driver, core); | ||
| 91 | } | 67 | } |
| 92 | static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device( | 68 | static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev( |
| 93 | struct work_struct *_work) | 69 | struct work_struct *_work) |
| 94 | { | 70 | { |
| 95 | struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work, | 71 | struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work, |
| @@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device( | |||
| 97 | return vw->dev; | 73 | return vw->dev; |
| 98 | } | 74 | } |
| 99 | 75 | ||
| 100 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | 76 | int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, |
| 101 | unsigned int bytes); | ||
| 102 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | ||
| 103 | unsigned int bytes); | 77 | unsigned int bytes); |
| 104 | int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, | 78 | int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, |
| 105 | unsigned int bytes); | 79 | unsigned int bytes); |
| 106 | void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev); | 80 | int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes); |
| 107 | void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, | 81 | void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev); |
| 82 | void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev, | ||
| 108 | unsigned int bytes); | 83 | unsigned int bytes); |
| 109 | 84 | ||
| 110 | #endif | 85 | #endif |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4e4c10a7fd3a..83b071b6ece4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -246,7 +246,7 @@ comment "Platform RTC drivers" | |||
| 246 | config RTC_DRV_CMOS | 246 | config RTC_DRV_CMOS |
| 247 | tristate "PC-style 'CMOS'" | 247 | tristate "PC-style 'CMOS'" |
| 248 | depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ | 248 | depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ |
| 249 | || M32R || ATARI || POWERPC || MIPS) | 249 | || M32R || ATARI || PPC || MIPS) |
| 250 | help | 250 | help |
| 251 | Say "yes" here to get direct support for the real time clock | 251 | Say "yes" here to get direct support for the real time clock |
| 252 | found in every PC or ACPI-based system, and some other boards. | 252 | found in every PC or ACPI-based system, and some other boards. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index b63ff8dd7304..cefde58dbad2 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
| @@ -678,7 +678,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 678 | } | 678 | } |
| 679 | bdp->cbd_datlen = count; | 679 | bdp->cbd_datlen = count; |
| 680 | bdp->cbd_sc |= BD_SC_READY; | 680 | bdp->cbd_sc |= BD_SC_READY; |
| 681 | __asm__("eieio"); | 681 | eieio(); |
| 682 | /* Get next BD. */ | 682 | /* Get next BD. */ |
| 683 | if (bdp->cbd_sc & BD_SC_WRAP) | 683 | if (bdp->cbd_sc & BD_SC_WRAP) |
| 684 | bdp = pinfo->tx_bd_base; | 684 | bdp = pinfo->tx_bd_base; |
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index 7ffdaeaf0545..a64d85821996 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c | |||
| @@ -17,6 +17,11 @@ | |||
| 17 | #include <asm/of_platform.h> | 17 | #include <asm/of_platform.h> |
| 18 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
| 19 | 19 | ||
| 20 | struct of_serial_info { | ||
| 21 | int type; | ||
| 22 | int line; | ||
| 23 | }; | ||
| 24 | |||
| 20 | /* | 25 | /* |
| 21 | * Fill a struct uart_port for a given device node | 26 | * Fill a struct uart_port for a given device node |
| 22 | */ | 27 | */ |
| @@ -62,6 +67,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, | |||
| 62 | static int __devinit of_platform_serial_probe(struct of_device *ofdev, | 67 | static int __devinit of_platform_serial_probe(struct of_device *ofdev, |
| 63 | const struct of_device_id *id) | 68 | const struct of_device_id *id) |
| 64 | { | 69 | { |
| 70 | struct of_serial_info *info; | ||
| 65 | struct uart_port port; | 71 | struct uart_port port; |
| 66 | int port_type; | 72 | int port_type; |
| 67 | int ret; | 73 | int ret; |
| @@ -69,30 +75,35 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev, | |||
| 69 | if (of_find_property(ofdev->node, "used-by-rtas", NULL)) | 75 | if (of_find_property(ofdev->node, "used-by-rtas", NULL)) |
| 70 | return -EBUSY; | 76 | return -EBUSY; |
| 71 | 77 | ||
| 78 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
| 79 | if (info == NULL) | ||
| 80 | return -ENOMEM; | ||
| 81 | |||
| 72 | port_type = (unsigned long)id->data; | 82 | port_type = (unsigned long)id->data; |
| 73 | ret = of_platform_serial_setup(ofdev, port_type, &port); | 83 | ret = of_platform_serial_setup(ofdev, port_type, &port); |
| 74 | if (ret) | 84 | if (ret) |
| 75 | goto out; | 85 | goto out; |
| 76 | 86 | ||
| 77 | switch (port_type) { | 87 | switch (port_type) { |
| 78 | case PORT_UNKNOWN: | ||
| 79 | dev_info(&ofdev->dev, "Unknown serial port found, " | ||
| 80 | "attempting to use 8250 driver\n"); | ||
| 81 | /* fallthrough */ | ||
| 82 | case PORT_8250 ... PORT_MAX_8250: | 88 | case PORT_8250 ... PORT_MAX_8250: |
| 83 | ret = serial8250_register_port(&port); | 89 | ret = serial8250_register_port(&port); |
| 84 | break; | 90 | break; |
| 85 | default: | 91 | default: |
| 86 | /* need to add code for these */ | 92 | /* need to add code for these */ |
| 93 | case PORT_UNKNOWN: | ||
| 94 | dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); | ||
| 87 | ret = -ENODEV; | 95 | ret = -ENODEV; |
| 88 | break; | 96 | break; |
| 89 | } | 97 | } |
| 90 | if (ret < 0) | 98 | if (ret < 0) |
| 91 | goto out; | 99 | goto out; |
| 92 | 100 | ||
| 93 | ofdev->dev.driver_data = (void *)(unsigned long)ret; | 101 | info->type = port_type; |
| 102 | info->line = ret; | ||
| 103 | ofdev->dev.driver_data = info; | ||
| 94 | return 0; | 104 | return 0; |
| 95 | out: | 105 | out: |
| 106 | kfree(info); | ||
| 96 | irq_dispose_mapping(port.irq); | 107 | irq_dispose_mapping(port.irq); |
| 97 | return ret; | 108 | return ret; |
| 98 | } | 109 | } |
| @@ -102,8 +113,16 @@ out: | |||
| 102 | */ | 113 | */ |
| 103 | static int of_platform_serial_remove(struct of_device *ofdev) | 114 | static int of_platform_serial_remove(struct of_device *ofdev) |
| 104 | { | 115 | { |
| 105 | int line = (unsigned long)ofdev->dev.driver_data; | 116 | struct of_serial_info *info = ofdev->dev.driver_data; |
| 106 | serial8250_unregister_port(line); | 117 | switch (info->type) { |
| 118 | case PORT_8250 ... PORT_MAX_8250: | ||
| 119 | serial8250_unregister_port(info->line); | ||
| 120 | break; | ||
| 121 | default: | ||
| 122 | /* need to add code for these */ | ||
| 123 | break; | ||
| 124 | } | ||
| 125 | kfree(info); | ||
| 107 | return 0; | 126 | return 0; |
| 108 | } | 127 | } |
| 109 | 128 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 403dac787ebf..9b7a76be36a0 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500 | |||
| 1790 | adaptor, found on some IBM System P (pSeries) machines. | 1790 | adaptor, found on some IBM System P (pSeries) machines. |
| 1791 | 1791 | ||
| 1792 | config FB_PS3 | 1792 | config FB_PS3 |
| 1793 | bool "PS3 GPU framebuffer driver" | 1793 | tristate "PS3 GPU framebuffer driver" |
| 1794 | depends on (FB = y) && PS3_PS3AV | 1794 | depends on FB && PS3_PS3AV |
| 1795 | select FB_SYS_FILLRECT | 1795 | select FB_SYS_FILLRECT |
| 1796 | select FB_SYS_COPYAREA | 1796 | select FB_SYS_COPYAREA |
| 1797 | select FB_SYS_IMAGEBLIT | 1797 | select FB_SYS_IMAGEBLIT |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 9cf92ba5d6e3..08b7ffbbbbd8 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
| 28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
| 29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 30 | #include <linux/platform_device.h> | ||
| 31 | #include <linux/console.h> | 30 | #include <linux/console.h> |
| 32 | #include <linux/ioctl.h> | 31 | #include <linux/ioctl.h> |
| 33 | #include <linux/notifier.h> | 32 | #include <linux/notifier.h> |
| @@ -46,6 +45,9 @@ | |||
| 46 | #include <asm/ps3fb.h> | 45 | #include <asm/ps3fb.h> |
| 47 | #include <asm/ps3.h> | 46 | #include <asm/ps3.h> |
| 48 | 47 | ||
| 48 | |||
| 49 | #define DEVICE_NAME "ps3fb" | ||
| 50 | |||
| 49 | #ifdef PS3FB_DEBUG | 51 | #ifdef PS3FB_DEBUG |
| 50 | #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args) | 52 | #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args) |
| 51 | #else | 53 | #else |
| @@ -126,7 +128,6 @@ struct gpu_driver_info { | |||
| 126 | 128 | ||
| 127 | struct ps3fb_priv { | 129 | struct ps3fb_priv { |
| 128 | unsigned int irq_no; | 130 | unsigned int irq_no; |
| 129 | void *dev; | ||
| 130 | 131 | ||
| 131 | u64 context_handle, memory_handle; | 132 | u64 context_handle, memory_handle; |
| 132 | void *xdr_ea; | 133 | void *xdr_ea; |
| @@ -171,7 +172,7 @@ static const struct ps3fb_res_table ps3fb_res[] = { | |||
| 171 | { 0, 0, 0, 0 , 0} }; | 172 | { 0, 0, 0, 0 , 0} }; |
| 172 | 173 | ||
| 173 | /* default resolution */ | 174 | /* default resolution */ |
| 174 | #define GPU_RES_INDEX 0 /* 720 x 480 */ | 175 | #define GPU_RES_INDEX 0 /* 720 x 480 */ |
| 175 | 176 | ||
| 176 | static const struct fb_videomode ps3fb_modedb[] = { | 177 | static const struct fb_videomode ps3fb_modedb[] = { |
| 177 | /* 60 Hz broadcast modes (modes "1" to "5") */ | 178 | /* 60 Hz broadcast modes (modes "1" to "5") */ |
| @@ -298,10 +299,9 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
| 298 | #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) | 299 | #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) |
| 299 | 300 | ||
| 300 | static int ps3fb_mode; | 301 | static int ps3fb_mode; |
| 301 | module_param(ps3fb_mode, bool, 0); | 302 | module_param(ps3fb_mode, int, 0); |
| 302 | |||
| 303 | static char *mode_option __initdata; | ||
| 304 | 303 | ||
| 304 | static char *mode_option __devinitdata; | ||
| 305 | 305 | ||
| 306 | static int ps3fb_get_res_table(u32 xres, u32 yres) | 306 | static int ps3fb_get_res_table(u32 xres, u32 yres) |
| 307 | { | 307 | { |
| @@ -681,15 +681,15 @@ int ps3fb_wait_for_vsync(u32 crtc) | |||
| 681 | 681 | ||
| 682 | EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync); | 682 | EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync); |
| 683 | 683 | ||
| 684 | void ps3fb_flip_ctl(int on) | 684 | void ps3fb_flip_ctl(int on, void *data) |
| 685 | { | 685 | { |
| 686 | struct ps3fb_priv *priv = data; | ||
| 686 | if (on) | 687 | if (on) |
| 687 | atomic_dec_if_positive(&ps3fb.ext_flip); | 688 | atomic_dec_if_positive(&priv->ext_flip); |
| 688 | else | 689 | else |
| 689 | atomic_inc(&ps3fb.ext_flip); | 690 | atomic_inc(&priv->ext_flip); |
| 690 | } | 691 | } |
| 691 | 692 | ||
| 692 | EXPORT_SYMBOL_GPL(ps3fb_flip_ctl); | ||
| 693 | 693 | ||
| 694 | /* | 694 | /* |
| 695 | * ioctl | 695 | * ioctl |
| @@ -851,37 +851,9 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) | |||
| 851 | return IRQ_HANDLED; | 851 | return IRQ_HANDLED; |
| 852 | } | 852 | } |
| 853 | 853 | ||
| 854 | #ifndef MODULE | ||
| 855 | static int __init ps3fb_setup(char *options) | ||
| 856 | { | ||
| 857 | char *this_opt; | ||
| 858 | int mode = 0; | ||
| 859 | |||
| 860 | if (!options || !*options) | ||
| 861 | return 0; /* no options */ | ||
| 862 | |||
| 863 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
| 864 | if (!*this_opt) | ||
| 865 | continue; | ||
| 866 | if (!strncmp(this_opt, "mode:", 5)) | ||
| 867 | mode = simple_strtoul(this_opt + 5, NULL, 0); | ||
| 868 | else | ||
| 869 | mode_option = this_opt; | ||
| 870 | } | ||
| 871 | return mode; | ||
| 872 | } | ||
| 873 | #endif /* MODULE */ | ||
| 874 | |||
| 875 | /* | ||
| 876 | * Initialisation | ||
| 877 | */ | ||
| 878 | 854 | ||
| 879 | static void ps3fb_platform_release(struct device *device) | 855 | static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, |
| 880 | { | 856 | struct ps3_system_bus_device *dev) |
| 881 | /* This is called when the reference count goes to zero. */ | ||
| 882 | } | ||
| 883 | |||
| 884 | static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | ||
| 885 | { | 857 | { |
| 886 | int error; | 858 | int error; |
| 887 | 859 | ||
| @@ -897,7 +869,6 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | |||
| 897 | return -EINVAL; | 869 | return -EINVAL; |
| 898 | } | 870 | } |
| 899 | 871 | ||
| 900 | ps3fb.dev = dev; | ||
| 901 | error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, | 872 | error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, |
| 902 | &ps3fb.irq_no); | 873 | &ps3fb.irq_no); |
| 903 | if (error) { | 874 | if (error) { |
| @@ -907,7 +878,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | |||
| 907 | } | 878 | } |
| 908 | 879 | ||
| 909 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, | 880 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, |
| 910 | "ps3fb vsync", ps3fb.dev); | 881 | DEVICE_NAME, dev); |
| 911 | if (error) { | 882 | if (error) { |
| 912 | printk(KERN_ERR "%s: request_irq failed %d\n", __func__, | 883 | printk(KERN_ERR "%s: request_irq failed %d\n", __func__, |
| 913 | error); | 884 | error); |
| @@ -966,16 +937,45 @@ static struct fb_ops ps3fb_ops = { | |||
| 966 | }; | 937 | }; |
| 967 | 938 | ||
| 968 | static struct fb_fix_screeninfo ps3fb_fix __initdata = { | 939 | static struct fb_fix_screeninfo ps3fb_fix __initdata = { |
| 969 | .id = "PS3 FB", | 940 | .id = DEVICE_NAME, |
| 970 | .type = FB_TYPE_PACKED_PIXELS, | 941 | .type = FB_TYPE_PACKED_PIXELS, |
| 971 | .visual = FB_VISUAL_TRUECOLOR, | 942 | .visual = FB_VISUAL_TRUECOLOR, |
| 972 | .accel = FB_ACCEL_NONE, | 943 | .accel = FB_ACCEL_NONE, |
| 973 | }; | 944 | }; |
| 974 | 945 | ||
| 975 | static int __init ps3fb_probe(struct platform_device *dev) | 946 | static int ps3fb_set_sync(void) |
| 947 | { | ||
| 948 | int status; | ||
| 949 | |||
| 950 | #ifdef HEAD_A | ||
| 951 | status = lv1_gpu_context_attribute(0x0, | ||
| 952 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
| 953 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
| 954 | if (status) { | ||
| 955 | printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC " | ||
| 956 | "failed: %d\n", __func__, status); | ||
| 957 | return -1; | ||
| 958 | } | ||
| 959 | #endif | ||
| 960 | #ifdef HEAD_B | ||
| 961 | status = lv1_gpu_context_attribute(0x0, | ||
| 962 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
| 963 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
| 964 | |||
| 965 | if (status) { | ||
| 966 | printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE " | ||
| 967 | "failed: %d\n", __func__, status); | ||
| 968 | return -1; | ||
| 969 | } | ||
| 970 | #endif | ||
| 971 | return 0; | ||
| 972 | } | ||
| 973 | |||
| 974 | static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | ||
| 976 | { | 975 | { |
| 977 | struct fb_info *info; | 976 | struct fb_info *info; |
| 978 | int retval = -ENOMEM; | 977 | int retval = -ENOMEM; |
| 978 | u32 xres, yres; | ||
| 979 | u64 ddr_lpar = 0; | 979 | u64 ddr_lpar = 0; |
| 980 | u64 lpar_dma_control = 0; | 980 | u64 lpar_dma_control = 0; |
| 981 | u64 lpar_driver_info = 0; | 981 | u64 lpar_driver_info = 0; |
| @@ -986,6 +986,30 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
| 986 | unsigned long offset; | 986 | unsigned long offset; |
| 987 | struct task_struct *task; | 987 | struct task_struct *task; |
| 988 | 988 | ||
| 989 | status = ps3_open_hv_device(dev); | ||
| 990 | if (status) { | ||
| 991 | printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__); | ||
| 992 | goto err; | ||
| 993 | } | ||
| 994 | |||
| 995 | if (!ps3fb_mode) | ||
| 996 | ps3fb_mode = ps3av_get_mode(); | ||
| 997 | DPRINTK("ps3av_mode:%d\n", ps3fb_mode); | ||
| 998 | |||
| 999 | if (ps3fb_mode > 0 && | ||
| 1000 | !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) { | ||
| 1001 | ps3fb.res_index = ps3fb_get_res_table(xres, yres); | ||
| 1002 | DPRINTK("res_index:%d\n", ps3fb.res_index); | ||
| 1003 | } else | ||
| 1004 | ps3fb.res_index = GPU_RES_INDEX; | ||
| 1005 | |||
| 1006 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | ||
| 1007 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | ||
| 1008 | init_waitqueue_head(&ps3fb.wait_vsync); | ||
| 1009 | ps3fb.num_frames = 1; | ||
| 1010 | |||
| 1011 | ps3fb_set_sync(); | ||
| 1012 | |||
| 989 | /* get gpu context handle */ | 1013 | /* get gpu context handle */ |
| 990 | status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, | 1014 | status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, |
| 991 | &ps3fb.memory_handle, &ddr_lpar); | 1015 | &ps3fb.memory_handle, &ddr_lpar); |
| @@ -1029,7 +1053,7 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
| 1029 | * leakage into userspace | 1053 | * leakage into userspace |
| 1030 | */ | 1054 | */ |
| 1031 | memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); | 1055 | memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); |
| 1032 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); | 1056 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->core); |
| 1033 | if (!info) | 1057 | if (!info) |
| 1034 | goto err_free_irq; | 1058 | goto err_free_irq; |
| 1035 | 1059 | ||
| @@ -1061,19 +1085,20 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
| 1061 | if (retval < 0) | 1085 | if (retval < 0) |
| 1062 | goto err_fb_dealloc; | 1086 | goto err_fb_dealloc; |
| 1063 | 1087 | ||
| 1064 | platform_set_drvdata(dev, info); | 1088 | dev->core.driver_data = info; |
| 1065 | 1089 | ||
| 1066 | printk(KERN_INFO | 1090 | printk(KERN_INFO |
| 1067 | "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", | 1091 | "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", |
| 1068 | info->node, ps3fb_videomemory.size >> 10); | 1092 | info->node, ps3fb_videomemory.size >> 10); |
| 1069 | 1093 | ||
| 1070 | task = kthread_run(ps3fbd, info, "ps3fbd"); | 1094 | task = kthread_run(ps3fbd, info, DEVICE_NAME); |
| 1071 | if (IS_ERR(task)) { | 1095 | if (IS_ERR(task)) { |
| 1072 | retval = PTR_ERR(task); | 1096 | retval = PTR_ERR(task); |
| 1073 | goto err_unregister_framebuffer; | 1097 | goto err_unregister_framebuffer; |
| 1074 | } | 1098 | } |
| 1075 | 1099 | ||
| 1076 | ps3fb.task = task; | 1100 | ps3fb.task = task; |
| 1101 | ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb); | ||
| 1077 | 1102 | ||
| 1078 | return 0; | 1103 | return 0; |
| 1079 | 1104 | ||
| @@ -1084,7 +1109,7 @@ err_fb_dealloc: | |||
| 1084 | err_framebuffer_release: | 1109 | err_framebuffer_release: |
| 1085 | framebuffer_release(info); | 1110 | framebuffer_release(info); |
| 1086 | err_free_irq: | 1111 | err_free_irq: |
| 1087 | free_irq(ps3fb.irq_no, ps3fb.dev); | 1112 | free_irq(ps3fb.irq_no, dev); |
| 1088 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1113 | ps3_irq_plug_destroy(ps3fb.irq_no); |
| 1089 | err_iounmap_dinfo: | 1114 | err_iounmap_dinfo: |
| 1090 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1115 | iounmap((u8 __iomem *)ps3fb.dinfo); |
| @@ -1096,26 +1121,30 @@ err: | |||
| 1096 | return retval; | 1121 | return retval; |
| 1097 | } | 1122 | } |
| 1098 | 1123 | ||
| 1099 | static void ps3fb_shutdown(struct platform_device *dev) | 1124 | static int ps3fb_shutdown(struct ps3_system_bus_device *dev) |
| 1100 | { | 1125 | { |
| 1101 | ps3fb_flip_ctl(0); /* flip off */ | 1126 | int status; |
| 1127 | struct fb_info *info = dev->core.driver_data; | ||
| 1128 | |||
| 1129 | DPRINTK(" -> %s:%d\n", __func__, __LINE__); | ||
| 1130 | |||
| 1131 | ps3fb_flip_ctl(0, &ps3fb); /* flip off */ | ||
| 1102 | ps3fb.dinfo->irq.mask = 0; | 1132 | ps3fb.dinfo->irq.mask = 0; |
| 1103 | free_irq(ps3fb.irq_no, ps3fb.dev); | ||
| 1104 | ps3_irq_plug_destroy(ps3fb.irq_no); | ||
| 1105 | iounmap((u8 __iomem *)ps3fb.dinfo); | ||
| 1106 | } | ||
| 1107 | 1133 | ||
| 1108 | void ps3fb_cleanup(void) | 1134 | if (info) { |
| 1109 | { | 1135 | unregister_framebuffer(info); |
| 1110 | int status; | 1136 | fb_dealloc_cmap(&info->cmap); |
| 1137 | framebuffer_release(info); | ||
| 1138 | } | ||
| 1111 | 1139 | ||
| 1140 | ps3av_register_flip_ctl(NULL, NULL); | ||
| 1112 | if (ps3fb.task) { | 1141 | if (ps3fb.task) { |
| 1113 | struct task_struct *task = ps3fb.task; | 1142 | struct task_struct *task = ps3fb.task; |
| 1114 | ps3fb.task = NULL; | 1143 | ps3fb.task = NULL; |
| 1115 | kthread_stop(task); | 1144 | kthread_stop(task); |
| 1116 | } | 1145 | } |
| 1117 | if (ps3fb.irq_no) { | 1146 | if (ps3fb.irq_no) { |
| 1118 | free_irq(ps3fb.irq_no, ps3fb.dev); | 1147 | free_irq(ps3fb.irq_no, dev); |
| 1119 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1148 | ps3_irq_plug_destroy(ps3fb.irq_no); |
| 1120 | } | 1149 | } |
| 1121 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1150 | iounmap((u8 __iomem *)ps3fb.dinfo); |
| @@ -1128,134 +1157,69 @@ void ps3fb_cleanup(void) | |||
| 1128 | if (status) | 1157 | if (status) |
| 1129 | DPRINTK("lv1_gpu_memory_free failed: %d\n", status); | 1158 | DPRINTK("lv1_gpu_memory_free failed: %d\n", status); |
| 1130 | 1159 | ||
| 1131 | ps3av_dev_close(); | 1160 | ps3_close_hv_device(dev); |
| 1132 | } | 1161 | DPRINTK(" <- %s:%d\n", __func__, __LINE__); |
| 1133 | 1162 | ||
| 1134 | EXPORT_SYMBOL_GPL(ps3fb_cleanup); | ||
| 1135 | |||
| 1136 | static int ps3fb_remove(struct platform_device *dev) | ||
| 1137 | { | ||
| 1138 | struct fb_info *info = platform_get_drvdata(dev); | ||
| 1139 | |||
| 1140 | if (info) { | ||
| 1141 | unregister_framebuffer(info); | ||
| 1142 | fb_dealloc_cmap(&info->cmap); | ||
| 1143 | framebuffer_release(info); | ||
| 1144 | } | ||
| 1145 | ps3fb_cleanup(); | ||
| 1146 | return 0; | 1163 | return 0; |
| 1147 | } | 1164 | } |
| 1148 | 1165 | ||
| 1149 | static struct platform_driver ps3fb_driver = { | 1166 | static struct ps3_system_bus_driver ps3fb_driver = { |
| 1150 | .probe = ps3fb_probe, | 1167 | .match_id = PS3_MATCH_ID_GRAPHICS, |
| 1151 | .remove = ps3fb_remove, | 1168 | .core.name = DEVICE_NAME, |
| 1152 | .shutdown = ps3fb_shutdown, | 1169 | .core.owner = THIS_MODULE, |
| 1153 | .driver = { .name = "ps3fb" } | 1170 | .probe = ps3fb_probe, |
| 1154 | }; | 1171 | .remove = ps3fb_shutdown, |
| 1155 | 1172 | .shutdown = ps3fb_shutdown, | |
| 1156 | static struct platform_device ps3fb_device = { | ||
| 1157 | .name = "ps3fb", | ||
| 1158 | .id = 0, | ||
| 1159 | .dev = { .release = ps3fb_platform_release } | ||
| 1160 | }; | 1173 | }; |
| 1161 | 1174 | ||
| 1162 | int ps3fb_set_sync(void) | 1175 | static int __init ps3fb_setup(void) |
| 1163 | { | 1176 | { |
| 1164 | int status; | 1177 | char *options; |
| 1165 | 1178 | ||
| 1166 | #ifdef HEAD_A | 1179 | #ifdef MODULE |
| 1167 | status = lv1_gpu_context_attribute(0x0, | ||
| 1168 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
| 1169 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
| 1170 | if (status) { | ||
| 1171 | printk(KERN_ERR | ||
| 1172 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", | ||
| 1173 | __func__, status); | ||
| 1174 | return -1; | ||
| 1175 | } | ||
| 1176 | #endif | ||
| 1177 | #ifdef HEAD_B | ||
| 1178 | status = lv1_gpu_context_attribute(0x0, | ||
| 1179 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
| 1180 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
| 1181 | |||
| 1182 | if (status) { | ||
| 1183 | printk(KERN_ERR | ||
| 1184 | "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", | ||
| 1185 | __func__, status); | ||
| 1186 | return -1; | ||
| 1187 | } | ||
| 1188 | #endif | ||
| 1189 | return 0; | 1180 | return 0; |
| 1190 | } | ||
| 1191 | |||
| 1192 | EXPORT_SYMBOL_GPL(ps3fb_set_sync); | ||
| 1193 | |||
| 1194 | static int __init ps3fb_init(void) | ||
| 1195 | { | ||
| 1196 | int error; | ||
| 1197 | #ifndef MODULE | ||
| 1198 | int mode; | ||
| 1199 | char *option = NULL; | ||
| 1200 | |||
| 1201 | if (fb_get_options("ps3fb", &option)) | ||
| 1202 | goto err; | ||
| 1203 | #endif | 1181 | #endif |
| 1204 | 1182 | ||
| 1205 | if (!ps3fb_videomemory.address) | 1183 | if (fb_get_options(DEVICE_NAME, &options)) |
| 1206 | goto err; | 1184 | return -ENXIO; |
| 1207 | |||
| 1208 | error = ps3av_dev_open(); | ||
| 1209 | if (error) { | ||
| 1210 | printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__); | ||
| 1211 | goto err; | ||
| 1212 | } | ||
| 1213 | 1185 | ||
| 1214 | ps3fb_mode = ps3av_get_mode(); | 1186 | if (!options || !*options) |
| 1215 | DPRINTK("ps3av_mode:%d\n", ps3fb_mode); | 1187 | return 0; |
| 1216 | #ifndef MODULE | ||
| 1217 | mode = ps3fb_setup(option); /* check boot option */ | ||
| 1218 | if (mode) | ||
| 1219 | ps3fb_mode = mode; | ||
| 1220 | #endif | ||
| 1221 | if (ps3fb_mode > 0) { | ||
| 1222 | u32 xres, yres; | ||
| 1223 | ps3av_video_mode2res(ps3fb_mode, &xres, &yres); | ||
| 1224 | ps3fb.res_index = ps3fb_get_res_table(xres, yres); | ||
| 1225 | DPRINTK("res_index:%d\n", ps3fb.res_index); | ||
| 1226 | } else | ||
| 1227 | ps3fb.res_index = GPU_RES_INDEX; | ||
| 1228 | 1188 | ||
| 1229 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1189 | while (1) { |
| 1230 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1190 | char *this_opt = strsep(&options, ","); |
| 1231 | init_waitqueue_head(&ps3fb.wait_vsync); | ||
| 1232 | ps3fb.num_frames = 1; | ||
| 1233 | 1191 | ||
| 1234 | error = platform_driver_register(&ps3fb_driver); | 1192 | if (!this_opt) |
| 1235 | if (!error) { | 1193 | break; |
| 1236 | error = platform_device_register(&ps3fb_device); | 1194 | if (!*this_opt) |
| 1237 | if (error) | 1195 | continue; |
| 1238 | platform_driver_unregister(&ps3fb_driver); | 1196 | if (!strncmp(this_opt, "mode:", 5)) |
| 1197 | ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0); | ||
| 1198 | else | ||
| 1199 | mode_option = this_opt; | ||
| 1239 | } | 1200 | } |
| 1201 | return 0; | ||
| 1202 | } | ||
| 1240 | 1203 | ||
| 1241 | ps3fb_set_sync(); | 1204 | static int __init ps3fb_init(void) |
| 1242 | 1205 | { | |
| 1243 | return error; | 1206 | if (!ps3fb_videomemory.address || ps3fb_setup()) |
| 1207 | return -ENXIO; | ||
| 1244 | 1208 | ||
| 1245 | err: | 1209 | return ps3_system_bus_driver_register(&ps3fb_driver); |
| 1246 | return -ENXIO; | ||
| 1247 | } | 1210 | } |
| 1248 | 1211 | ||
| 1249 | module_init(ps3fb_init); | ||
| 1250 | |||
| 1251 | #ifdef MODULE | ||
| 1252 | static void __exit ps3fb_exit(void) | 1212 | static void __exit ps3fb_exit(void) |
| 1253 | { | 1213 | { |
| 1254 | platform_device_unregister(&ps3fb_device); | 1214 | DPRINTK(" -> %s:%d\n", __func__, __LINE__); |
| 1255 | platform_driver_unregister(&ps3fb_driver); | 1215 | ps3_system_bus_driver_unregister(&ps3fb_driver); |
| 1216 | DPRINTK(" <- %s:%d\n", __func__, __LINE__); | ||
| 1256 | } | 1217 | } |
| 1257 | 1218 | ||
| 1219 | module_init(ps3fb_init); | ||
| 1258 | module_exit(ps3fb_exit); | 1220 | module_exit(ps3fb_exit); |
| 1259 | 1221 | ||
| 1260 | MODULE_LICENSE("GPL"); | 1222 | MODULE_LICENSE("GPL"); |
| 1261 | #endif /* MODULE */ | 1223 | MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver"); |
| 1224 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); | ||
| 1225 | MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS); | ||
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h index 642be62cf393..53507046a1b1 100644 --- a/include/asm-powerpc/cache.h +++ b/include/asm-powerpc/cache.h | |||
| @@ -34,5 +34,9 @@ struct ppc64_caches { | |||
| 34 | extern struct ppc64_caches ppc64_caches; | 34 | extern struct ppc64_caches ppc64_caches; |
| 35 | #endif /* __powerpc64__ && ! __ASSEMBLY__ */ | 35 | #endif /* __powerpc64__ && ! __ASSEMBLY__ */ |
| 36 | 36 | ||
| 37 | #if !defined(__ASSEMBLY__) | ||
| 38 | #define __read_mostly __attribute__((__section__(".data.read_mostly"))) | ||
| 39 | #endif | ||
| 40 | |||
| 37 | #endif /* __KERNEL__ */ | 41 | #endif /* __KERNEL__ */ |
| 38 | #endif /* _ASM_POWERPC_CACHE_H */ | 42 | #endif /* _ASM_POWERPC_CACHE_H */ |
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 82d595a52109..3dc8e2dfca84 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
| @@ -111,7 +111,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
| 111 | /* CPU kernel features */ | 111 | /* CPU kernel features */ |
| 112 | 112 | ||
| 113 | /* Retain the 32b definitions all use bottom half of word */ | 113 | /* Retain the 32b definitions all use bottom half of word */ |
| 114 | #define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) | 114 | #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000000000000001) |
| 115 | #define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) | 115 | #define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) |
| 116 | #define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) | 116 | #define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) |
| 117 | #define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) | 117 | #define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) |
| @@ -135,6 +135,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
| 135 | #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) | 135 | #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) |
| 136 | #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) | 136 | #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) |
| 137 | #define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) | 137 | #define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) |
| 138 | #define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000) | ||
| 138 | 139 | ||
| 139 | /* | 140 | /* |
| 140 | * Add the 64-bit processor unique features in the top half of the word; | 141 | * Add the 64-bit processor unique features in the top half of the word; |
| @@ -154,7 +155,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
| 154 | #define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) | 155 | #define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) |
| 155 | #define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) | 156 | #define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) |
| 156 | #define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000) | 157 | #define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000) |
| 157 | #define CPU_FTR_COHERENT_ICACHE LONG_ASM_CONST(0x0000020000000000) | ||
| 158 | #define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000) | 158 | #define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000) |
| 159 | #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) | 159 | #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) |
| 160 | #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) | 160 | #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) |
| @@ -206,164 +206,149 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
| 206 | !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ | 206 | !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ |
| 207 | !defined(CONFIG_BOOKE)) | 207 | !defined(CONFIG_BOOKE)) |
| 208 | 208 | ||
| 209 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE) | 209 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \ |
| 210 | #define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 210 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) |
| 211 | #define CPU_FTRS_603 (CPU_FTR_COMMON | \ | ||
| 211 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ | 212 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ |
| 212 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) | 213 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) |
| 213 | #define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 214 | #define CPU_FTRS_604 (CPU_FTR_COMMON | \ |
| 214 | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \ | 215 | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \ |
| 215 | CPU_FTR_PPC_LE) | 216 | CPU_FTR_PPC_LE) |
| 216 | #define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 217 | #define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | \ |
| 217 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 218 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ |
| 218 | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) | 219 | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) |
| 219 | #define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 220 | #define CPU_FTRS_740 (CPU_FTR_COMMON | \ |
| 220 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 221 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ |
| 221 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | 222 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ |
| 222 | CPU_FTR_PPC_LE) | 223 | CPU_FTR_PPC_LE) |
| 223 | #define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 224 | #define CPU_FTRS_750 (CPU_FTR_COMMON | \ |
| 224 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 225 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ |
| 225 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | 226 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ |
| 226 | CPU_FTR_PPC_LE) | 227 | CPU_FTR_PPC_LE) |
| 227 | #define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 228 | #define CPU_FTRS_750CL (CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS) |
| 228 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 229 | #define CPU_FTRS_750FX1 (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM) |
| 229 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | 230 | #define CPU_FTRS_750FX2 (CPU_FTRS_750 | CPU_FTR_NO_DPM) |
| 230 | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) | 231 | #define CPU_FTRS_750FX (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \ |
| 231 | #define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 232 | CPU_FTR_HAS_HIGH_BATS) |
| 232 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 233 | #define CPU_FTRS_750GX (CPU_FTRS_750FX) |
| 233 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | 234 | #define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | \ |
| 234 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) | ||
| 235 | #define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | ||
| 236 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | ||
| 237 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | ||
| 238 | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) | ||
| 239 | #define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | ||
| 240 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | ||
| 241 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | ||
| 242 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) | ||
| 243 | #define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | ||
| 244 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | ||
| 245 | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ | ||
| 246 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) | ||
| 247 | #define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | ||
| 248 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 235 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ |
| 249 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ | 236 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ |
| 250 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) | 237 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) |
| 251 | #define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 238 | #define CPU_FTRS_7400 (CPU_FTR_COMMON | \ |
| 252 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ | 239 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ |
| 253 | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ | 240 | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ |
| 254 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) | 241 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) |
| 255 | #define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 242 | #define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \ |
| 256 | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 243 | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 257 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 244 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 258 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 245 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 259 | #define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 246 | #define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \ |
| 260 | CPU_FTR_USE_TB | \ | 247 | CPU_FTR_USE_TB | \ |
| 261 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 248 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 262 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 249 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 263 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ | 250 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ |
| 264 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 251 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 265 | #define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 252 | #define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \ |
| 266 | CPU_FTR_USE_TB | \ | 253 | CPU_FTR_USE_TB | \ |
| 267 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 254 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 268 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 255 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 269 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 256 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 270 | #define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 257 | #define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \ |
| 271 | CPU_FTR_USE_TB | \ | 258 | CPU_FTR_USE_TB | \ |
| 272 | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \ | 259 | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \ |
| 273 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \ | 260 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \ |
| 274 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 261 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 275 | #define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 262 | #define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \ |
| 276 | CPU_FTR_USE_TB | \ | 263 | CPU_FTR_USE_TB | \ |
| 277 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 264 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 278 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 265 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 279 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ | 266 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ |
| 280 | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) | 267 | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) |
| 281 | #define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 268 | #define CPU_FTRS_7455 (CPU_FTR_COMMON | \ |
| 282 | CPU_FTR_USE_TB | \ | 269 | CPU_FTR_USE_TB | \ |
| 283 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 270 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 284 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 271 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 285 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ | 272 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ |
| 286 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 273 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 287 | #define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 274 | #define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \ |
| 288 | CPU_FTR_USE_TB | \ | 275 | CPU_FTR_USE_TB | \ |
| 289 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 276 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 290 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 277 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 291 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ | 278 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ |
| 292 | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE) | 279 | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE) |
| 293 | #define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 280 | #define CPU_FTRS_7447 (CPU_FTR_COMMON | \ |
| 294 | CPU_FTR_USE_TB | \ | 281 | CPU_FTR_USE_TB | \ |
| 295 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 282 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 296 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 283 | CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 297 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ | 284 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ |
| 298 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 285 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 299 | #define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 286 | #define CPU_FTRS_7447A (CPU_FTR_COMMON | \ |
| 300 | CPU_FTR_USE_TB | \ | 287 | CPU_FTR_USE_TB | \ |
| 301 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 288 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 302 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 289 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 303 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ | 290 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ |
| 304 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) | 291 | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) |
| 305 | #define CPU_FTRS_7448 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 292 | #define CPU_FTRS_7448 (CPU_FTR_COMMON | \ |
| 306 | CPU_FTR_USE_TB | \ | 293 | CPU_FTR_USE_TB | \ |
| 307 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ | 294 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ |
| 308 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ | 295 | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ |
| 309 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ | 296 | CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ |
| 310 | CPU_FTR_PPC_LE) | 297 | CPU_FTR_PPC_LE) |
| 311 | #define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 298 | #define CPU_FTRS_82XX (CPU_FTR_COMMON | \ |
| 312 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB) | 299 | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB) |
| 313 | #define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ | 300 | #define CPU_FTRS_G2_LE (CPU_FTR_MAYBE_CAN_DOZE | \ |
| 314 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS) | 301 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS) |
| 315 | #define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ | 302 | #define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \ |
| 316 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ | 303 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ |
| 317 | CPU_FTR_COMMON) | 304 | CPU_FTR_COMMON) |
| 318 | #define CPU_FTRS_E300C2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ | 305 | #define CPU_FTRS_E300C2 (CPU_FTR_MAYBE_CAN_DOZE | \ |
| 319 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ | 306 | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ |
| 320 | CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE) | 307 | CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE) |
| 321 | #define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ | 308 | #define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | \ |
| 322 | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) | 309 | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) |
| 323 | #define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB) | 310 | #define CPU_FTRS_8XX (CPU_FTR_USE_TB) |
| 324 | #define CPU_FTRS_40X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 311 | #define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) |
| 325 | CPU_FTR_NODSISRALIGN) | 312 | #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) |
| 326 | #define CPU_FTRS_44X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 313 | #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \ |
| 327 | CPU_FTR_NODSISRALIGN) | 314 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) |
| 328 | #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) | 315 | #define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) |
| 329 | #define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 316 | #define CPU_FTRS_E500_2 (CPU_FTR_USE_TB | \ |
| 330 | CPU_FTR_NODSISRALIGN) | ||
| 331 | #define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | ||
| 332 | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) | 317 | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) |
| 333 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) | 318 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) |
| 334 | 319 | ||
| 335 | /* 64-bit CPUs */ | 320 | /* 64-bit CPUs */ |
| 336 | #define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 321 | #define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \ |
| 337 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) | 322 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) |
| 338 | #define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 323 | #define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \ |
| 339 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \ | 324 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \ |
| 340 | CPU_FTR_MMCRA | CPU_FTR_CTRL) | 325 | CPU_FTR_MMCRA | CPU_FTR_CTRL) |
| 341 | #define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 326 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | \ |
| 342 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 327 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 343 | CPU_FTR_MMCRA) | 328 | CPU_FTR_MMCRA) |
| 344 | #define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 329 | #define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | \ |
| 345 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 330 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 346 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA) | 331 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA) |
| 347 | #define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 332 | #define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | \ |
| 348 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 333 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 349 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 334 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
| 350 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 335 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
| 351 | CPU_FTR_PURR) | 336 | CPU_FTR_PURR) |
| 352 | #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 337 | #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \ |
| 353 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 338 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 354 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 339 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
| 355 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 340 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
| 356 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 341 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
| 357 | CPU_FTR_DSCR) | 342 | CPU_FTR_DSCR) |
| 358 | #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 343 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | \ |
| 359 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 344 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 360 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 345 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
| 361 | CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG) | 346 | CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG) |
| 362 | #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 347 | #define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \ |
| 363 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ | 348 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ |
| 364 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ | 349 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ |
| 365 | CPU_FTR_PURR | CPU_FTR_REAL_LE) | 350 | CPU_FTR_PURR | CPU_FTR_REAL_LE) |
| 366 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 351 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | \ |
| 367 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) | 352 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) |
| 368 | 353 | ||
| 369 | #ifdef __powerpc64__ | 354 | #ifdef __powerpc64__ |
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h index afa700ded877..34146f0eea63 100644 --- a/include/asm-powerpc/floppy.h +++ b/include/asm-powerpc/floppy.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); | 29 | #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); |
| 30 | 30 | ||
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | #include <asm/ppc-pci.h> /* for ppc64_isabridge_dev */ | 32 | #include <asm/ppc-pci.h> /* for isa_bridge_pcidev */ |
| 33 | 33 | ||
| 34 | #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io) | 34 | #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io) |
| 35 | 35 | ||
| @@ -139,12 +139,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) | |||
| 139 | if (bus_addr | 139 | if (bus_addr |
| 140 | && (addr != prev_addr || size != prev_size || dir != prev_dir)) { | 140 | && (addr != prev_addr || size != prev_size || dir != prev_dir)) { |
| 141 | /* different from last time -- unmap prev */ | 141 | /* different from last time -- unmap prev */ |
| 142 | pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir); | 142 | pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir); |
| 143 | bus_addr = 0; | 143 | bus_addr = 0; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | if (!bus_addr) /* need to map it */ | 146 | if (!bus_addr) /* need to map it */ |
| 147 | bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir); | 147 | bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir); |
| 148 | 148 | ||
| 149 | /* remember this one as prev */ | 149 | /* remember this one as prev */ |
| 150 | prev_addr = addr; | 150 | prev_addr = addr; |
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index 62efd9d7a43d..bf6cd7cb996c 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
| @@ -206,6 +206,7 @@ | |||
| 206 | #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 | 206 | #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 |
| 207 | #define H_QUERY_INT_STATE 0x1E4 | 207 | #define H_QUERY_INT_STATE 0x1E4 |
| 208 | #define H_POLL_PENDING 0x1D8 | 208 | #define H_POLL_PENDING 0x1D8 |
| 209 | #define H_ILLAN_ATTRIBUTES 0x244 | ||
| 209 | #define H_JOIN 0x298 | 210 | #define H_JOIN 0x298 |
| 210 | #define H_VASI_STATE 0x2A4 | 211 | #define H_VASI_STATE 0x2A4 |
| 211 | #define H_ENABLE_CRQ 0x2B0 | 212 | #define H_ENABLE_CRQ 0x2B0 |
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 350c9bdb31dc..bb8d965f96c6 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h | |||
| @@ -607,9 +607,9 @@ static inline void iosync(void) | |||
| 607 | * | 607 | * |
| 608 | * * iounmap undoes such a mapping and can be hooked | 608 | * * iounmap undoes such a mapping and can be hooked |
| 609 | * | 609 | * |
| 610 | * * __ioremap_explicit (and the pending __iounmap_explicit) are low level | 610 | * * __ioremap_at (and the pending __iounmap_at) are low level functions to |
| 611 | * functions to create hand-made mappings for use only by the PCI code | 611 | * create hand-made mappings for use only by the PCI code and cannot |
| 612 | * and cannot currently be hooked. | 612 | * currently be hooked. Must be page aligned. |
| 613 | * | 613 | * |
| 614 | * * __ioremap is the low level implementation used by ioremap and | 614 | * * __ioremap is the low level implementation used by ioremap and |
| 615 | * ioremap_flags and cannot be hooked (but can be used by a hook on one | 615 | * ioremap_flags and cannot be hooked (but can be used by a hook on one |
| @@ -629,19 +629,9 @@ extern void __iomem *__ioremap(phys_addr_t, unsigned long size, | |||
| 629 | unsigned long flags); | 629 | unsigned long flags); |
| 630 | extern void __iounmap(volatile void __iomem *addr); | 630 | extern void __iounmap(volatile void __iomem *addr); |
| 631 | 631 | ||
| 632 | extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr, | 632 | extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea, |
| 633 | unsigned long size, unsigned long flags); | 633 | unsigned long size, unsigned long flags); |
| 634 | extern int __iounmap_explicit(volatile void __iomem *start, | 634 | extern void __iounmap_at(void *ea, unsigned long size); |
| 635 | unsigned long size); | ||
| 636 | |||
| 637 | extern void __iomem * reserve_phb_iospace(unsigned long size); | ||
| 638 | |||
| 639 | /* Those are more 32 bits only functions */ | ||
| 640 | extern unsigned long iopa(unsigned long addr); | ||
| 641 | extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; | ||
| 642 | extern void io_block_mapping(unsigned long virt, phys_addr_t phys, | ||
| 643 | unsigned int size, int flags); | ||
| 644 | |||
| 645 | 635 | ||
| 646 | /* | 636 | /* |
| 647 | * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation | 637 | * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation |
| @@ -651,8 +641,8 @@ extern void io_block_mapping(unsigned long virt, phys_addr_t phys, | |||
| 651 | */ | 641 | */ |
| 652 | #define HAVE_ARCH_PIO_SIZE 1 | 642 | #define HAVE_ARCH_PIO_SIZE 1 |
| 653 | #define PIO_OFFSET 0x00000000UL | 643 | #define PIO_OFFSET 0x00000000UL |
| 654 | #define PIO_MASK 0x3fffffffUL | 644 | #define PIO_MASK (FULL_IO_SIZE - 1) |
| 655 | #define PIO_RESERVED 0x40000000UL | 645 | #define PIO_RESERVED (FULL_IO_SIZE) |
| 656 | 646 | ||
| 657 | #define mmio_read16be(addr) readw_be(addr) | 647 | #define mmio_read16be(addr) readw_be(addr) |
| 658 | #define mmio_read32be(addr) readl_be(addr) | 648 | #define mmio_read32be(addr) readl_be(addr) |
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 05dd5a3eb3aa..0485c53db2b5 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h | |||
| @@ -223,6 +223,15 @@ extern void irq_dispose_mapping(unsigned int virq); | |||
| 223 | extern unsigned int irq_find_mapping(struct irq_host *host, | 223 | extern unsigned int irq_find_mapping(struct irq_host *host, |
| 224 | irq_hw_number_t hwirq); | 224 | irq_hw_number_t hwirq); |
| 225 | 225 | ||
| 226 | /** | ||
| 227 | * irq_create_direct_mapping - Allocate a virq for direct mapping | ||
| 228 | * @host: host to allocate the virq for or NULL for default host | ||
| 229 | * | ||
| 230 | * This routine is used for irq controllers which can choose the hardware | ||
| 231 | * interrupt numbers they generate. In such a case it's simplest to use | ||
| 232 | * the linux virq as the hardware interrupt number. | ||
| 233 | */ | ||
| 234 | extern unsigned int irq_create_direct_mapping(struct irq_host *host); | ||
| 226 | 235 | ||
| 227 | /** | 236 | /** |
| 228 | * irq_radix_revmap - Find a linux virq from a hw irq number. | 237 | * irq_radix_revmap - Find a linux virq from a hw irq number. |
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index 821ea0c512b4..567ed92cd91f 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h | |||
| @@ -98,7 +98,7 @@ struct lppaca { | |||
| 98 | u64 saved_gpr5; // Saved GPR5 x30-x37 | 98 | u64 saved_gpr5; // Saved GPR5 x30-x37 |
| 99 | 99 | ||
| 100 | u8 reserved4; // Reserved x38-x38 | 100 | u8 reserved4; // Reserved x38-x38 |
| 101 | u8 cpuctls_task_attrs; // Task attributes for cpuctls x39-x39 | 101 | u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39 |
| 102 | u8 fpregs_in_use; // FP regs in use x3A-x3A | 102 | u8 fpregs_in_use; // FP regs in use x3A-x3A |
| 103 | u8 pmcregs_in_use; // PMC regs in use x3B-x3B | 103 | u8 pmcregs_in_use; // PMC regs in use x3B-x3B |
| 104 | volatile u32 saved_decr; // Saved Decr Value x3C-x3F | 104 | volatile u32 saved_decr; // Saved Decr Value x3C-x3F |
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h index f733beeea63a..81713acf7529 100644 --- a/include/asm-powerpc/lv1call.h +++ b/include/asm-powerpc/lv1call.h | |||
| @@ -238,6 +238,7 @@ LV1_CALL(destruct_virtual_address_space, 1, 0, 10 ) | |||
| 238 | LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) | 238 | LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) |
| 239 | LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) | 239 | LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) |
| 240 | LV1_CALL(release_memory, 1, 0, 13 ) | 240 | LV1_CALL(release_memory, 1, 0, 13 ) |
| 241 | LV1_CALL(put_iopte, 5, 0, 15 ) | ||
| 241 | LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) | 242 | LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) |
| 242 | LV1_CALL(construct_event_receive_port, 0, 1, 18 ) | 243 | LV1_CALL(construct_event_receive_port, 0, 1, 18 ) |
| 243 | LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) | 244 | LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) |
| @@ -268,6 +269,8 @@ LV1_CALL(remove_repository_node, 4, 0, 93 ) | |||
| 268 | LV1_CALL(read_htab_entries, 2, 5, 95 ) | 269 | LV1_CALL(read_htab_entries, 2, 5, 95 ) |
| 269 | LV1_CALL(set_dabr, 2, 0, 96 ) | 270 | LV1_CALL(set_dabr, 2, 0, 96 ) |
| 270 | LV1_CALL(get_total_execution_time, 2, 1, 103 ) | 271 | LV1_CALL(get_total_execution_time, 2, 1, 103 ) |
| 272 | LV1_CALL(allocate_io_segment, 3, 1, 116 ) | ||
| 273 | LV1_CALL(release_io_segment, 2, 0, 117 ) | ||
| 271 | LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) | 274 | LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) |
| 272 | LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) | 275 | LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) |
| 273 | LV1_CALL(map_htab, 1, 1, 122 ) | 276 | LV1_CALL(map_htab, 1, 1, 122 ) |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 6cf1a831f550..71c6e7eb2a26 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
| @@ -218,7 +218,7 @@ struct machdep_calls { | |||
| 218 | int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); | 218 | int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); |
| 219 | 219 | ||
| 220 | /* Called in indirect_* to avoid touching devices */ | 220 | /* Called in indirect_* to avoid touching devices */ |
| 221 | int (*pci_exclude_device)(unsigned char, unsigned char); | 221 | int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char); |
| 222 | 222 | ||
| 223 | /* Called at then very end of pcibios_init() */ | 223 | /* Called at then very end of pcibios_init() */ |
| 224 | void (*pcibios_after_init)(void); | 224 | void (*pcibios_after_init)(void); |
diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h new file mode 100644 index 000000000000..952bd8899f2f --- /dev/null +++ b/include/asm-powerpc/mmu-8xx.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | #ifndef _ASM_POWERPC_MMU_8XX_H_ | ||
| 2 | #define _ASM_POWERPC_MMU_8XX_H_ | ||
| 3 | /* | ||
| 4 | * PPC8xx support | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* Control/status registers for the MPC8xx. | ||
| 8 | * A write operation to these registers causes serialized access. | ||
| 9 | * During software tablewalk, the registers used perform mask/shift-add | ||
| 10 | * operations when written/read. A TLB entry is created when the Mx_RPN | ||
| 11 | * is written, and the contents of several registers are used to | ||
| 12 | * create the entry. | ||
| 13 | */ | ||
| 14 | #define SPRN_MI_CTR 784 /* Instruction TLB control register */ | ||
| 15 | #define MI_GPM 0x80000000 /* Set domain manager mode */ | ||
| 16 | #define MI_PPM 0x40000000 /* Set subpage protection */ | ||
| 17 | #define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ | ||
| 18 | #define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */ | ||
| 19 | #define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ | ||
| 20 | #define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */ | ||
| 21 | #define MI_RESETVAL 0x00000000 /* Value of register at reset */ | ||
| 22 | |||
| 23 | /* These are the Ks and Kp from the PowerPC books. For proper operation, | ||
| 24 | * Ks = 0, Kp = 1. | ||
| 25 | */ | ||
| 26 | #define SPRN_MI_AP 786 | ||
| 27 | #define MI_Ks 0x80000000 /* Should not be set */ | ||
| 28 | #define MI_Kp 0x40000000 /* Should always be set */ | ||
| 29 | |||
| 30 | /* The effective page number register. When read, contains the information | ||
| 31 | * about the last instruction TLB miss. When MI_RPN is written, bits in | ||
| 32 | * this register are used to create the TLB entry. | ||
| 33 | */ | ||
| 34 | #define SPRN_MI_EPN 787 | ||
| 35 | #define MI_EPNMASK 0xfffff000 /* Effective page number for entry */ | ||
| 36 | #define MI_EVALID 0x00000200 /* Entry is valid */ | ||
| 37 | #define MI_ASIDMASK 0x0000000f /* ASID match value */ | ||
| 38 | /* Reset value is undefined */ | ||
| 39 | |||
| 40 | /* A "level 1" or "segment" or whatever you want to call it register. | ||
| 41 | * For the instruction TLB, it contains bits that get loaded into the | ||
| 42 | * TLB entry when the MI_RPN is written. | ||
| 43 | */ | ||
| 44 | #define SPRN_MI_TWC 789 | ||
| 45 | #define MI_APG 0x000001e0 /* Access protection group (0) */ | ||
| 46 | #define MI_GUARDED 0x00000010 /* Guarded storage */ | ||
| 47 | #define MI_PSMASK 0x0000000c /* Mask of page size bits */ | ||
| 48 | #define MI_PS8MEG 0x0000000c /* 8M page size */ | ||
| 49 | #define MI_PS512K 0x00000004 /* 512K page size */ | ||
| 50 | #define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */ | ||
| 51 | #define MI_SVALID 0x00000001 /* Segment entry is valid */ | ||
| 52 | /* Reset value is undefined */ | ||
| 53 | |||
| 54 | /* Real page number. Defined by the pte. Writing this register | ||
| 55 | * causes a TLB entry to be created for the instruction TLB, using | ||
| 56 | * additional information from the MI_EPN, and MI_TWC registers. | ||
| 57 | */ | ||
| 58 | #define SPRN_MI_RPN 790 | ||
| 59 | |||
| 60 | /* Define an RPN value for mapping kernel memory to large virtual | ||
| 61 | * pages for boot initialization. This has real page number of 0, | ||
| 62 | * large page size, shared page, cache enabled, and valid. | ||
| 63 | * Also mark all subpages valid and write access. | ||
| 64 | */ | ||
| 65 | #define MI_BOOTINIT 0x000001fd | ||
| 66 | |||
| 67 | #define SPRN_MD_CTR 792 /* Data TLB control register */ | ||
| 68 | #define MD_GPM 0x80000000 /* Set domain manager mode */ | ||
| 69 | #define MD_PPM 0x40000000 /* Set subpage protection */ | ||
| 70 | #define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ | ||
| 71 | #define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */ | ||
| 72 | #define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */ | ||
| 73 | #define MD_TWAM 0x04000000 /* Use 4K page hardware assist */ | ||
| 74 | #define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ | ||
| 75 | #define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */ | ||
| 76 | #define MD_RESETVAL 0x04000000 /* Value of register at reset */ | ||
| 77 | |||
| 78 | #define SPRN_M_CASID 793 /* Address space ID (context) to match */ | ||
| 79 | #define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */ | ||
| 80 | |||
| 81 | |||
| 82 | /* These are the Ks and Kp from the PowerPC books. For proper operation, | ||
| 83 | * Ks = 0, Kp = 1. | ||
| 84 | */ | ||
| 85 | #define SPRN_MD_AP 794 | ||
| 86 | #define MD_Ks 0x80000000 /* Should not be set */ | ||
| 87 | #define MD_Kp 0x40000000 /* Should always be set */ | ||
| 88 | |||
| 89 | /* The effective page number register. When read, contains the information | ||
| 90 | * about the last instruction TLB miss. When MD_RPN is written, bits in | ||
| 91 | * this register are used to create the TLB entry. | ||
| 92 | */ | ||
| 93 | #define SPRN_MD_EPN 795 | ||
| 94 | #define MD_EPNMASK 0xfffff000 /* Effective page number for entry */ | ||
| 95 | #define MD_EVALID 0x00000200 /* Entry is valid */ | ||
| 96 | #define MD_ASIDMASK 0x0000000f /* ASID match value */ | ||
| 97 | /* Reset value is undefined */ | ||
| 98 | |||
| 99 | /* The pointer to the base address of the first level page table. | ||
| 100 | * During a software tablewalk, reading this register provides the address | ||
| 101 | * of the entry associated with MD_EPN. | ||
| 102 | */ | ||
| 103 | #define SPRN_M_TWB 796 | ||
| 104 | #define M_L1TB 0xfffff000 /* Level 1 table base address */ | ||
| 105 | #define M_L1INDX 0x00000ffc /* Level 1 index, when read */ | ||
| 106 | /* Reset value is undefined */ | ||
| 107 | |||
| 108 | /* A "level 1" or "segment" or whatever you want to call it register. | ||
| 109 | * For the data TLB, it contains bits that get loaded into the TLB entry | ||
| 110 | * when the MD_RPN is written. It is also provides the hardware assist | ||
| 111 | * for finding the PTE address during software tablewalk. | ||
| 112 | */ | ||
| 113 | #define SPRN_MD_TWC 797 | ||
| 114 | #define MD_L2TB 0xfffff000 /* Level 2 table base address */ | ||
| 115 | #define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */ | ||
| 116 | #define MD_APG 0x000001e0 /* Access protection group (0) */ | ||
| 117 | #define MD_GUARDED 0x00000010 /* Guarded storage */ | ||
| 118 | #define MD_PSMASK 0x0000000c /* Mask of page size bits */ | ||
| 119 | #define MD_PS8MEG 0x0000000c /* 8M page size */ | ||
| 120 | #define MD_PS512K 0x00000004 /* 512K page size */ | ||
| 121 | #define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */ | ||
| 122 | #define MD_WT 0x00000002 /* Use writethrough page attribute */ | ||
| 123 | #define MD_SVALID 0x00000001 /* Segment entry is valid */ | ||
| 124 | /* Reset value is undefined */ | ||
| 125 | |||
| 126 | |||
| 127 | /* Real page number. Defined by the pte. Writing this register | ||
| 128 | * causes a TLB entry to be created for the data TLB, using | ||
| 129 | * additional information from the MD_EPN, and MD_TWC registers. | ||
| 130 | */ | ||
| 131 | #define SPRN_MD_RPN 798 | ||
| 132 | |||
| 133 | /* This is a temporary storage register that could be used to save | ||
| 134 | * a processor working register during a tablewalk. | ||
| 135 | */ | ||
| 136 | #define SPRN_M_TW 799 | ||
| 137 | |||
| 138 | #ifndef __ASSEMBLY__ | ||
| 139 | typedef unsigned long phys_addr_t; | ||
| 140 | |||
| 141 | typedef struct { | ||
| 142 | unsigned long id; | ||
| 143 | unsigned long vdso_base; | ||
| 144 | } mm_context_t; | ||
| 145 | #endif /* !__ASSEMBLY__ */ | ||
| 146 | |||
| 147 | #endif /* _ASM_POWERPC_MMU_8XX_H_ */ | ||
diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h new file mode 100644 index 000000000000..37580004cd7a --- /dev/null +++ b/include/asm-powerpc/mmu-fsl-booke.h | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | #ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_ | ||
| 2 | #define _ASM_POWERPC_MMU_FSL_BOOKE_H_ | ||
| 3 | /* | ||
| 4 | * Freescale Book-E MMU support | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* Book-E defined page sizes */ | ||
| 8 | #define BOOKE_PAGESZ_1K 0 | ||
| 9 | #define BOOKE_PAGESZ_4K 1 | ||
| 10 | #define BOOKE_PAGESZ_16K 2 | ||
| 11 | #define BOOKE_PAGESZ_64K 3 | ||
| 12 | #define BOOKE_PAGESZ_256K 4 | ||
| 13 | #define BOOKE_PAGESZ_1M 5 | ||
| 14 | #define BOOKE_PAGESZ_4M 6 | ||
| 15 | #define BOOKE_PAGESZ_16M 7 | ||
| 16 | #define BOOKE_PAGESZ_64M 8 | ||
| 17 | #define BOOKE_PAGESZ_256M 9 | ||
| 18 | #define BOOKE_PAGESZ_1GB 10 | ||
| 19 | #define BOOKE_PAGESZ_4GB 11 | ||
| 20 | #define BOOKE_PAGESZ_16GB 12 | ||
| 21 | #define BOOKE_PAGESZ_64GB 13 | ||
| 22 | #define BOOKE_PAGESZ_256GB 14 | ||
| 23 | #define BOOKE_PAGESZ_1TB 15 | ||
| 24 | |||
| 25 | #define MAS0_TLBSEL(x) ((x << 28) & 0x30000000) | ||
| 26 | #define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000) | ||
| 27 | #define MAS0_NV(x) ((x) & 0x00000FFF) | ||
| 28 | |||
| 29 | #define MAS1_VALID 0x80000000 | ||
| 30 | #define MAS1_IPROT 0x40000000 | ||
| 31 | #define MAS1_TID(x) ((x << 16) & 0x3FFF0000) | ||
| 32 | #define MAS1_TS 0x00001000 | ||
| 33 | #define MAS1_TSIZE(x) ((x << 8) & 0x00000F00) | ||
| 34 | |||
| 35 | #define MAS2_EPN 0xFFFFF000 | ||
| 36 | #define MAS2_X0 0x00000040 | ||
| 37 | #define MAS2_X1 0x00000020 | ||
| 38 | #define MAS2_W 0x00000010 | ||
| 39 | #define MAS2_I 0x00000008 | ||
| 40 | #define MAS2_M 0x00000004 | ||
| 41 | #define MAS2_G 0x00000002 | ||
| 42 | #define MAS2_E 0x00000001 | ||
| 43 | |||
| 44 | #define MAS3_RPN 0xFFFFF000 | ||
| 45 | #define MAS3_U0 0x00000200 | ||
| 46 | #define MAS3_U1 0x00000100 | ||
| 47 | #define MAS3_U2 0x00000080 | ||
| 48 | #define MAS3_U3 0x00000040 | ||
| 49 | #define MAS3_UX 0x00000020 | ||
| 50 | #define MAS3_SX 0x00000010 | ||
| 51 | #define MAS3_UW 0x00000008 | ||
| 52 | #define MAS3_SW 0x00000004 | ||
| 53 | #define MAS3_UR 0x00000002 | ||
| 54 | #define MAS3_SR 0x00000001 | ||
| 55 | |||
| 56 | #define MAS4_TLBSELD(x) MAS0_TLBSEL(x) | ||
| 57 | #define MAS4_TIDDSEL 0x000F0000 | ||
| 58 | #define MAS4_TSIZED(x) MAS1_TSIZE(x) | ||
| 59 | #define MAS4_X0D 0x00000040 | ||
| 60 | #define MAS4_X1D 0x00000020 | ||
| 61 | #define MAS4_WD 0x00000010 | ||
| 62 | #define MAS4_ID 0x00000008 | ||
| 63 | #define MAS4_MD 0x00000004 | ||
| 64 | #define MAS4_GD 0x00000002 | ||
| 65 | #define MAS4_ED 0x00000001 | ||
| 66 | |||
| 67 | #define MAS6_SPID0 0x3FFF0000 | ||
| 68 | #define MAS6_SPID1 0x00007FFE | ||
| 69 | #define MAS6_SAS 0x00000001 | ||
| 70 | #define MAS6_SPID MAS6_SPID0 | ||
| 71 | |||
| 72 | #define MAS7_RPN 0xFFFFFFFF | ||
| 73 | |||
| 74 | #ifndef __ASSEMBLY__ | ||
| 75 | |||
| 76 | #ifndef CONFIG_PHYS_64BIT | ||
| 77 | typedef unsigned long phys_addr_t; | ||
| 78 | #else | ||
| 79 | typedef unsigned long long phys_addr_t; | ||
| 80 | #endif | ||
| 81 | |||
| 82 | typedef struct { | ||
| 83 | unsigned long id; | ||
| 84 | unsigned long vdso_base; | ||
| 85 | } mm_context_t; | ||
| 86 | #endif /* !__ASSEMBLY__ */ | ||
| 87 | |||
| 88 | #endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */ | ||
diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h new file mode 100644 index 000000000000..4bd735be3833 --- /dev/null +++ b/include/asm-powerpc/mmu-hash32.h | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | #ifndef _ASM_POWERPC_MMU_HASH32_H_ | ||
| 2 | #define _ASM_POWERPC_MMU_HASH32_H_ | ||
| 3 | /* | ||
| 4 | * 32-bit hash table MMU support | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * BATs | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* Block size masks */ | ||
| 12 | #define BL_128K 0x000 | ||
| 13 | #define BL_256K 0x001 | ||
| 14 | #define BL_512K 0x003 | ||
| 15 | #define BL_1M 0x007 | ||
| 16 | #define BL_2M 0x00F | ||
| 17 | #define BL_4M 0x01F | ||
| 18 | #define BL_8M 0x03F | ||
| 19 | #define BL_16M 0x07F | ||
| 20 | #define BL_32M 0x0FF | ||
| 21 | #define BL_64M 0x1FF | ||
| 22 | #define BL_128M 0x3FF | ||
| 23 | #define BL_256M 0x7FF | ||
| 24 | |||
| 25 | /* BAT Access Protection */ | ||
| 26 | #define BPP_XX 0x00 /* No access */ | ||
| 27 | #define BPP_RX 0x01 /* Read only */ | ||
| 28 | #define BPP_RW 0x02 /* Read/write */ | ||
| 29 | |||
| 30 | #ifndef __ASSEMBLY__ | ||
| 31 | struct ppc_bat { | ||
| 32 | struct { | ||
| 33 | unsigned long bepi:15; /* Effective page index (virtual address) */ | ||
| 34 | unsigned long :4; /* Unused */ | ||
| 35 | unsigned long bl:11; /* Block size mask */ | ||
| 36 | unsigned long vs:1; /* Supervisor valid */ | ||
| 37 | unsigned long vp:1; /* User valid */ | ||
| 38 | } batu; /* Upper register */ | ||
| 39 | struct { | ||
| 40 | unsigned long brpn:15; /* Real page index (physical address) */ | ||
| 41 | unsigned long :10; /* Unused */ | ||
| 42 | unsigned long w:1; /* Write-thru cache */ | ||
| 43 | unsigned long i:1; /* Cache inhibit */ | ||
| 44 | unsigned long m:1; /* Memory coherence */ | ||
| 45 | unsigned long g:1; /* Guarded (MBZ in IBAT) */ | ||
| 46 | unsigned long :1; /* Unused */ | ||
| 47 | unsigned long pp:2; /* Page access protections */ | ||
| 48 | } batl; /* Lower register */ | ||
| 49 | }; | ||
| 50 | #endif /* !__ASSEMBLY__ */ | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Hash table | ||
| 54 | */ | ||
| 55 | |||
| 56 | /* Values for PP (assumes Ks=0, Kp=1) */ | ||
| 57 | #define PP_RWXX 0 /* Supervisor read/write, User none */ | ||
| 58 | #define PP_RWRX 1 /* Supervisor read/write, User read */ | ||
| 59 | #define PP_RWRW 2 /* Supervisor read/write, User read/write */ | ||
| 60 | #define PP_RXRX 3 /* Supervisor read, User read */ | ||
| 61 | |||
| 62 | #ifndef __ASSEMBLY__ | ||
| 63 | |||
| 64 | /* Hardware Page Table Entry */ | ||
| 65 | struct hash_pte { | ||
| 66 | unsigned long v:1; /* Entry is valid */ | ||
| 67 | unsigned long vsid:24; /* Virtual segment identifier */ | ||
| 68 | unsigned long h:1; /* Hash algorithm indicator */ | ||
| 69 | unsigned long api:6; /* Abbreviated page index */ | ||
| 70 | unsigned long rpn:20; /* Real (physical) page number */ | ||
| 71 | unsigned long :3; /* Unused */ | ||
| 72 | unsigned long r:1; /* Referenced */ | ||
| 73 | unsigned long c:1; /* Changed */ | ||
| 74 | unsigned long w:1; /* Write-thru cache mode */ | ||
| 75 | unsigned long i:1; /* Cache inhibited */ | ||
| 76 | unsigned long m:1; /* Memory coherence */ | ||
| 77 | unsigned long g:1; /* Guarded */ | ||
| 78 | unsigned long :1; /* Unused */ | ||
| 79 | unsigned long pp:2; /* Page protection */ | ||
| 80 | }; | ||
| 81 | |||
| 82 | typedef struct { | ||
| 83 | unsigned long id; | ||
| 84 | unsigned long vdso_base; | ||
| 85 | } mm_context_t; | ||
| 86 | |||
| 87 | typedef unsigned long phys_addr_t; | ||
| 88 | |||
| 89 | #endif /* !__ASSEMBLY__ */ | ||
| 90 | |||
| 91 | #endif /* _ASM_POWERPC_MMU_HASH32_H_ */ | ||
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h index b8dca30bd0b5..695962f02059 100644 --- a/include/asm-powerpc/mmu-hash64.h +++ b/include/asm-powerpc/mmu-hash64.h | |||
| @@ -94,6 +94,9 @@ extern char initial_stab[]; | |||
| 94 | #define HPTE_R_C ASM_CONST(0x0000000000000080) | 94 | #define HPTE_R_C ASM_CONST(0x0000000000000080) |
| 95 | #define HPTE_R_R ASM_CONST(0x0000000000000100) | 95 | #define HPTE_R_R ASM_CONST(0x0000000000000100) |
| 96 | 96 | ||
| 97 | #define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000) | ||
| 98 | #define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000) | ||
| 99 | |||
| 97 | /* Values for PP (assumes Ks=0, Kp=1) */ | 100 | /* Values for PP (assumes Ks=0, Kp=1) */ |
| 98 | /* pp0 will always be 0 for linux */ | 101 | /* pp0 will always be 0 for linux */ |
| 99 | #define PP_RWXX 0 /* Supervisor read/write, User none */ | 102 | #define PP_RWXX 0 /* Supervisor read/write, User none */ |
| @@ -103,12 +106,12 @@ extern char initial_stab[]; | |||
| 103 | 106 | ||
| 104 | #ifndef __ASSEMBLY__ | 107 | #ifndef __ASSEMBLY__ |
| 105 | 108 | ||
| 106 | typedef struct { | 109 | struct hash_pte { |
| 107 | unsigned long v; | 110 | unsigned long v; |
| 108 | unsigned long r; | 111 | unsigned long r; |
| 109 | } hpte_t; | 112 | }; |
| 110 | 113 | ||
| 111 | extern hpte_t *htab_address; | 114 | extern struct hash_pte *htab_address; |
| 112 | extern unsigned long htab_size_bytes; | 115 | extern unsigned long htab_size_bytes; |
| 113 | extern unsigned long htab_hash_mask; | 116 | extern unsigned long htab_hash_mask; |
| 114 | 117 | ||
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index fe510fff8907..d44d211e7588 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h | |||
| @@ -5,13 +5,18 @@ | |||
| 5 | #ifdef CONFIG_PPC64 | 5 | #ifdef CONFIG_PPC64 |
| 6 | /* 64-bit classic hash table MMU */ | 6 | /* 64-bit classic hash table MMU */ |
| 7 | # include <asm/mmu-hash64.h> | 7 | # include <asm/mmu-hash64.h> |
| 8 | #elif defined(CONFIG_PPC_STD_MMU) | ||
| 9 | /* 32-bit classic hash table MMU */ | ||
| 10 | # include <asm/mmu-hash32.h> | ||
| 8 | #elif defined(CONFIG_44x) | 11 | #elif defined(CONFIG_44x) |
| 9 | /* 44x-style software loaded TLB */ | 12 | /* 44x-style software loaded TLB */ |
| 10 | # include <asm/mmu-44x.h> | 13 | # include <asm/mmu-44x.h> |
| 11 | #else | 14 | #elif defined(CONFIG_FSL_BOOKE) |
| 12 | /* Other 32-bit. FIXME: split up the other 32-bit MMU types, and | 15 | /* Freescale Book-E software loaded TLB */ |
| 13 | * revise for arch/powerpc */ | 16 | # include <asm/mmu-fsl-booke.h> |
| 14 | # include <asm-ppc/mmu.h> | 17 | #elif defined (CONFIG_PPC_8xx) |
| 18 | /* Motorola/Freescale 8xx software loaded TLB */ | ||
| 19 | # include <asm/mmu-8xx.h> | ||
| 15 | #endif | 20 | #endif |
| 16 | 21 | ||
| 17 | #endif /* __KERNEL__ */ | 22 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h index 40c9e5a13ff1..f863ac21409e 100644 --- a/include/asm-powerpc/mmu_context.h +++ b/include/asm-powerpc/mmu_context.h | |||
| @@ -2,16 +2,210 @@ | |||
| 2 | #define __ASM_POWERPC_MMU_CONTEXT_H | 2 | #define __ASM_POWERPC_MMU_CONTEXT_H |
| 3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
| 4 | 4 | ||
| 5 | #include <asm/mmu.h> | ||
| 6 | #include <asm/cputable.h> | ||
| 7 | #include <asm-generic/mm_hooks.h> | ||
| 8 | |||
| 5 | #ifndef CONFIG_PPC64 | 9 | #ifndef CONFIG_PPC64 |
| 6 | #include <asm-ppc/mmu_context.h> | 10 | #include <asm/atomic.h> |
| 11 | #include <asm/bitops.h> | ||
| 12 | |||
| 13 | /* | ||
| 14 | * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs | ||
| 15 | * (virtual segment identifiers) for each context. Although the | ||
| 16 | * hardware supports 24-bit VSIDs, and thus >1 million contexts, | ||
| 17 | * we only use 32,768 of them. That is ample, since there can be | ||
| 18 | * at most around 30,000 tasks in the system anyway, and it means | ||
| 19 | * that we can use a bitmap to indicate which contexts are in use. | ||
| 20 | * Using a bitmap means that we entirely avoid all of the problems | ||
| 21 | * that we used to have when the context number overflowed, | ||
| 22 | * particularly on SMP systems. | ||
| 23 | * -- paulus. | ||
| 24 | */ | ||
| 25 | |||
| 26 | /* | ||
| 27 | * This function defines the mapping from contexts to VSIDs (virtual | ||
| 28 | * segment IDs). We use a skew on both the context and the high 4 bits | ||
| 29 | * of the 32-bit virtual address (the "effective segment ID") in order | ||
| 30 | * to spread out the entries in the MMU hash table. Note, if this | ||
| 31 | * function is changed then arch/ppc/mm/hashtable.S will have to be | ||
| 32 | * changed to correspond. | ||
| 33 | */ | ||
| 34 | #define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \ | ||
| 35 | & 0xffffff) | ||
| 36 | |||
| 37 | /* | ||
| 38 | The MPC8xx has only 16 contexts. We rotate through them on each | ||
| 39 | task switch. A better way would be to keep track of tasks that | ||
| 40 | own contexts, and implement an LRU usage. That way very active | ||
| 41 | tasks don't always have to pay the TLB reload overhead. The | ||
| 42 | kernel pages are mapped shared, so the kernel can run on behalf | ||
| 43 | of any task that makes a kernel entry. Shared does not mean they | ||
| 44 | are not protected, just that the ASID comparison is not performed. | ||
| 45 | -- Dan | ||
| 46 | |||
| 47 | The IBM4xx has 256 contexts, so we can just rotate through these | ||
| 48 | as a way of "switching" contexts. If the TID of the TLB is zero, | ||
| 49 | the PID/TID comparison is disabled, so we can use a TID of zero | ||
| 50 | to represent all kernel pages as shared among all contexts. | ||
| 51 | -- Dan | ||
| 52 | */ | ||
| 53 | |||
| 54 | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | ||
| 55 | { | ||
| 56 | } | ||
| 57 | |||
| 58 | #ifdef CONFIG_8xx | ||
| 59 | #define NO_CONTEXT 16 | ||
| 60 | #define LAST_CONTEXT 15 | ||
| 61 | #define FIRST_CONTEXT 0 | ||
| 62 | |||
| 63 | #elif defined(CONFIG_4xx) | ||
| 64 | #define NO_CONTEXT 256 | ||
| 65 | #define LAST_CONTEXT 255 | ||
| 66 | #define FIRST_CONTEXT 1 | ||
| 67 | |||
| 68 | #elif defined(CONFIG_E200) || defined(CONFIG_E500) | ||
| 69 | #define NO_CONTEXT 256 | ||
| 70 | #define LAST_CONTEXT 255 | ||
| 71 | #define FIRST_CONTEXT 1 | ||
| 72 | |||
| 73 | #else | ||
| 74 | |||
| 75 | /* PPC 6xx, 7xx CPUs */ | ||
| 76 | #define NO_CONTEXT ((unsigned long) -1) | ||
| 77 | #define LAST_CONTEXT 32767 | ||
| 78 | #define FIRST_CONTEXT 1 | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* | ||
| 82 | * Set the current MMU context. | ||
| 83 | * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by | ||
| 84 | * loading up the segment registers for the user part of the address space. | ||
| 85 | * | ||
| 86 | * Since the PGD is immediately available, it is much faster to simply | ||
| 87 | * pass this along as a second parameter, which is required for 8xx and | ||
| 88 | * can be used for debugging on all processors (if you happen to have | ||
| 89 | * an Abatron). | ||
| 90 | */ | ||
| 91 | extern void set_context(unsigned long contextid, pgd_t *pgd); | ||
| 92 | |||
| 93 | /* | ||
| 94 | * Bitmap of contexts in use. | ||
| 95 | * The size of this bitmap is LAST_CONTEXT + 1 bits. | ||
| 96 | */ | ||
| 97 | extern unsigned long context_map[]; | ||
| 98 | |||
| 99 | /* | ||
| 100 | * This caches the next context number that we expect to be free. | ||
| 101 | * Its use is an optimization only, we can't rely on this context | ||
| 102 | * number to be free, but it usually will be. | ||
| 103 | */ | ||
| 104 | extern unsigned long next_mmu_context; | ||
| 105 | |||
| 106 | /* | ||
| 107 | * If we don't have sufficient contexts to give one to every task | ||
| 108 | * that could be in the system, we need to be able to steal contexts. | ||
| 109 | * These variables support that. | ||
| 110 | */ | ||
| 111 | #if LAST_CONTEXT < 30000 | ||
| 112 | #define FEW_CONTEXTS 1 | ||
| 113 | extern atomic_t nr_free_contexts; | ||
| 114 | extern struct mm_struct *context_mm[LAST_CONTEXT+1]; | ||
| 115 | extern void steal_context(void); | ||
| 116 | #endif | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Get a new mmu context for the address space described by `mm'. | ||
| 120 | */ | ||
| 121 | static inline void get_mmu_context(struct mm_struct *mm) | ||
| 122 | { | ||
| 123 | unsigned long ctx; | ||
| 124 | |||
| 125 | if (mm->context.id != NO_CONTEXT) | ||
| 126 | return; | ||
| 127 | #ifdef FEW_CONTEXTS | ||
| 128 | while (atomic_dec_if_positive(&nr_free_contexts) < 0) | ||
| 129 | steal_context(); | ||
| 130 | #endif | ||
| 131 | ctx = next_mmu_context; | ||
| 132 | while (test_and_set_bit(ctx, context_map)) { | ||
| 133 | ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx); | ||
| 134 | if (ctx > LAST_CONTEXT) | ||
| 135 | ctx = 0; | ||
| 136 | } | ||
| 137 | next_mmu_context = (ctx + 1) & LAST_CONTEXT; | ||
| 138 | mm->context.id = ctx; | ||
| 139 | #ifdef FEW_CONTEXTS | ||
| 140 | context_mm[ctx] = mm; | ||
| 141 | #endif | ||
| 142 | } | ||
| 143 | |||
| 144 | /* | ||
| 145 | * Set up the context for a new address space. | ||
| 146 | */ | ||
| 147 | static inline int init_new_context(struct task_struct *t, struct mm_struct *mm) | ||
| 148 | { | ||
| 149 | mm->context.id = NO_CONTEXT; | ||
| 150 | mm->context.vdso_base = 0; | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | * We're finished using the context for an address space. | ||
| 156 | */ | ||
| 157 | static inline void destroy_context(struct mm_struct *mm) | ||
| 158 | { | ||
| 159 | preempt_disable(); | ||
| 160 | if (mm->context.id != NO_CONTEXT) { | ||
| 161 | clear_bit(mm->context.id, context_map); | ||
| 162 | mm->context.id = NO_CONTEXT; | ||
| 163 | #ifdef FEW_CONTEXTS | ||
| 164 | atomic_inc(&nr_free_contexts); | ||
| 165 | #endif | ||
| 166 | } | ||
| 167 | preempt_enable(); | ||
| 168 | } | ||
| 169 | |||
| 170 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
| 171 | struct task_struct *tsk) | ||
| 172 | { | ||
| 173 | #ifdef CONFIG_ALTIVEC | ||
| 174 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
| 175 | asm volatile ("dssall;\n" | ||
| 176 | #ifndef CONFIG_POWER4 | ||
| 177 | "sync;\n" /* G4 needs a sync here, G5 apparently not */ | ||
| 178 | #endif | ||
| 179 | : : ); | ||
| 180 | #endif /* CONFIG_ALTIVEC */ | ||
| 181 | |||
| 182 | tsk->thread.pgdir = next->pgd; | ||
| 183 | |||
| 184 | /* No need to flush userspace segments if the mm doesnt change */ | ||
| 185 | if (prev == next) | ||
| 186 | return; | ||
| 187 | |||
| 188 | /* Setup new userspace context */ | ||
| 189 | get_mmu_context(next); | ||
| 190 | set_context(next->context.id, next->pgd); | ||
| 191 | } | ||
| 192 | |||
| 193 | #define deactivate_mm(tsk,mm) do { } while (0) | ||
| 194 | |||
| 195 | /* | ||
| 196 | * After we have set current->mm to a new value, this activates | ||
| 197 | * the context for the new mm so we see the new mappings. | ||
| 198 | */ | ||
| 199 | #define activate_mm(active_mm, mm) switch_mm(active_mm, mm, current) | ||
| 200 | |||
| 201 | extern void mmu_context_init(void); | ||
| 202 | |||
| 203 | |||
| 7 | #else | 204 | #else |
| 8 | 205 | ||
| 9 | #include <linux/kernel.h> | 206 | #include <linux/kernel.h> |
| 10 | #include <linux/mm.h> | 207 | #include <linux/mm.h> |
| 11 | #include <linux/sched.h> | 208 | #include <linux/sched.h> |
| 12 | #include <asm/mmu.h> | ||
| 13 | #include <asm/cputable.h> | ||
| 14 | #include <asm-generic/mm_hooks.h> | ||
| 15 | 209 | ||
| 16 | /* | 210 | /* |
| 17 | * Copyright (C) 2001 PPC 64 Team, IBM Corp | 211 | * Copyright (C) 2001 PPC 64 Team, IBM Corp |
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h index b85df45b1a84..15f650f987e7 100644 --- a/include/asm-powerpc/mpc86xx.h +++ b/include/asm-powerpc/mpc86xx.h | |||
| @@ -19,12 +19,6 @@ | |||
| 19 | 19 | ||
| 20 | #ifdef CONFIG_PPC_86xx | 20 | #ifdef CONFIG_PPC_86xx |
| 21 | 21 | ||
| 22 | #define _IO_BASE isa_io_base | ||
| 23 | #define _ISA_MEM_BASE isa_mem_base | ||
| 24 | #ifdef CONFIG_PCI | ||
| 25 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #define CPU0_BOOT_RELEASE 0x01000000 | 22 | #define CPU0_BOOT_RELEASE 0x01000000 |
| 29 | #define CPU1_BOOT_RELEASE 0x02000000 | 23 | #define CPU1_BOOT_RELEASE 0x02000000 |
| 30 | #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE) | 24 | #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE) |
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h index 580371120e1a..2be014b6f57c 100644 --- a/include/asm-powerpc/mpc8xx.h +++ b/include/asm-powerpc/mpc8xx.h | |||
| @@ -23,6 +23,10 @@ | |||
| 23 | #include <platforms/8xx/mpc885ads.h> | 23 | #include <platforms/8xx/mpc885ads.h> |
| 24 | #endif | 24 | #endif |
| 25 | 25 | ||
| 26 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 27 | extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
| 28 | #endif | ||
| 29 | |||
| 26 | #endif /* CONFIG_8xx */ | 30 | #endif /* CONFIG_8xx */ |
| 27 | #endif /* __CONFIG_8xx_DEFS */ | 31 | #endif /* __CONFIG_8xx_DEFS */ |
| 28 | #endif /* __KERNEL__ */ | 32 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index d9bf5aba96cb..e72c2a60853c 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h | |||
| @@ -2,12 +2,91 @@ | |||
| 2 | #define _ASM_POWERPC_PCI_BRIDGE_H | 2 | #define _ASM_POWERPC_PCI_BRIDGE_H |
| 3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
| 4 | 4 | ||
| 5 | #include <linux/pci.h> | ||
| 6 | #include <linux/list.h> | ||
| 7 | #include <linux/ioport.h> | ||
| 8 | |||
| 5 | #ifndef CONFIG_PPC64 | 9 | #ifndef CONFIG_PPC64 |
| 6 | #include <asm-ppc/pci-bridge.h> | 10 | |
| 11 | struct device_node; | ||
| 12 | struct pci_controller; | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Structure of a PCI controller (host bridge) | ||
| 16 | */ | ||
| 17 | struct pci_controller { | ||
| 18 | struct pci_bus *bus; | ||
| 19 | char is_dynamic; | ||
| 20 | void *arch_data; | ||
| 21 | struct list_head list_node; | ||
| 22 | struct device *parent; | ||
| 23 | |||
| 24 | int first_busno; | ||
| 25 | int last_busno; | ||
| 26 | int self_busno; | ||
| 27 | |||
| 28 | void __iomem *io_base_virt; | ||
| 29 | resource_size_t io_base_phys; | ||
| 30 | |||
| 31 | /* Some machines (PReP) have a non 1:1 mapping of | ||
| 32 | * the PCI memory space in the CPU bus space | ||
| 33 | */ | ||
| 34 | resource_size_t pci_mem_offset; | ||
| 35 | |||
| 36 | struct pci_ops *ops; | ||
| 37 | volatile unsigned int __iomem *cfg_addr; | ||
| 38 | volatile void __iomem *cfg_data; | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Used for variants of PCI indirect handling and possible quirks: | ||
| 42 | * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1 | ||
| 43 | * EXT_REG - provides access to PCI-e extended registers | ||
| 44 | * SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS | ||
| 45 | * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS | ||
| 46 | * to determine which bus number to match on when generating type0 | ||
| 47 | * config cycles | ||
| 48 | */ | ||
| 49 | #define PPC_INDIRECT_TYPE_SET_CFG_TYPE (0x00000001) | ||
| 50 | #define PPC_INDIRECT_TYPE_EXT_REG (0x00000002) | ||
| 51 | #define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS (0x00000004) | ||
| 52 | u32 indirect_type; | ||
| 53 | |||
| 54 | /* Currently, we limit ourselves to 1 IO range and 3 mem | ||
| 55 | * ranges since the common pci_bus structure can't handle more | ||
| 56 | */ | ||
| 57 | struct resource io_resource; | ||
| 58 | struct resource mem_resources[3]; | ||
| 59 | int global_number; /* PCI domain number */ | ||
| 60 | }; | ||
| 61 | |||
| 62 | static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) | ||
| 63 | { | ||
| 64 | return bus->sysdata; | ||
| 65 | } | ||
| 66 | |||
| 67 | /* These are used for config access before all the PCI probing | ||
| 68 | has been done. */ | ||
| 69 | int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn, | ||
| 70 | int where, u8 *val); | ||
| 71 | int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn, | ||
| 72 | int where, u16 *val); | ||
| 73 | int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn, | ||
| 74 | int where, u32 *val); | ||
| 75 | int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn, | ||
| 76 | int where, u8 val); | ||
| 77 | int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn, | ||
| 78 | int where, u16 val); | ||
| 79 | int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn, | ||
| 80 | int where, u32 val); | ||
| 81 | |||
| 82 | extern void setup_indirect_pci_nomap(struct pci_controller* hose, | ||
| 83 | void __iomem *cfg_addr, void __iomem *cfg_data); | ||
| 84 | extern void setup_indirect_pci(struct pci_controller* hose, | ||
| 85 | u32 cfg_addr, u32 cfg_data); | ||
| 86 | extern void setup_grackle(struct pci_controller *hose); | ||
| 87 | |||
| 7 | #else | 88 | #else |
| 8 | 89 | ||
| 9 | #include <linux/pci.h> | ||
| 10 | #include <linux/list.h> | ||
| 11 | 90 | ||
| 12 | /* | 91 | /* |
| 13 | * This program is free software; you can redistribute it and/or | 92 | * This program is free software; you can redistribute it and/or |
| @@ -31,6 +110,7 @@ struct pci_controller { | |||
| 31 | int last_busno; | 110 | int last_busno; |
| 32 | 111 | ||
| 33 | void __iomem *io_base_virt; | 112 | void __iomem *io_base_virt; |
| 113 | void *io_base_alloc; | ||
| 34 | resource_size_t io_base_phys; | 114 | resource_size_t io_base_phys; |
| 35 | 115 | ||
| 36 | /* Some machines have a non 1:1 mapping of | 116 | /* Some machines have a non 1:1 mapping of |
| @@ -48,8 +128,7 @@ struct pci_controller { | |||
| 48 | */ | 128 | */ |
| 49 | struct resource io_resource; | 129 | struct resource io_resource; |
| 50 | struct resource mem_resources[3]; | 130 | struct resource mem_resources[3]; |
| 51 | int global_number; | 131 | int global_number; |
| 52 | int local_number; | ||
| 53 | unsigned long buid; | 132 | unsigned long buid; |
| 54 | unsigned long dma_window_base_cur; | 133 | unsigned long dma_window_base_cur; |
| 55 | unsigned long dma_window_size; | 134 | unsigned long dma_window_size; |
| @@ -70,19 +149,22 @@ struct pci_dn { | |||
| 70 | int devfn; /* pci device and function number */ | 149 | int devfn; /* pci device and function number */ |
| 71 | int class_code; /* pci device class */ | 150 | int class_code; /* pci device class */ |
| 72 | 151 | ||
| 73 | #ifdef CONFIG_PPC_PSERIES | 152 | struct pci_controller *phb; /* for pci devices */ |
| 153 | struct iommu_table *iommu_table; /* for phb's or bridges */ | ||
| 154 | struct pci_dev *pcidev; /* back-pointer to the pci device */ | ||
| 155 | struct device_node *node; /* back-pointer to the device_node */ | ||
| 156 | |||
| 157 | int pci_ext_config_space; /* for pci devices */ | ||
| 158 | |||
| 159 | #ifdef CONFIG_EEH | ||
| 74 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ | 160 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ |
| 75 | int eeh_config_addr; | 161 | int eeh_config_addr; |
| 76 | int eeh_pe_config_addr; /* new-style partition endpoint address */ | 162 | int eeh_pe_config_addr; /* new-style partition endpoint address */ |
| 77 | int eeh_check_count; /* # times driver ignored error */ | 163 | int eeh_check_count; /* # times driver ignored error */ |
| 78 | int eeh_freeze_count; /* # times this device froze up. */ | 164 | int eeh_freeze_count; /* # times this device froze up. */ |
| 79 | #endif | 165 | int eeh_false_positives; /* # times this device reported #ff's */ |
| 80 | int pci_ext_config_space; /* for pci devices */ | ||
| 81 | struct pci_controller *phb; /* for pci devices */ | ||
| 82 | struct iommu_table *iommu_table; /* for phb's or bridges */ | ||
| 83 | struct pci_dev *pcidev; /* back-pointer to the pci device */ | ||
| 84 | struct device_node *node; /* back-pointer to the device_node */ | ||
| 85 | u32 config_space[16]; /* saved PCI config space */ | 166 | u32 config_space[16]; /* saved PCI config space */ |
| 167 | #endif | ||
| 86 | }; | 168 | }; |
| 87 | 169 | ||
| 88 | /* Get the pointer to a device_node's pci_dn */ | 170 | /* Get the pointer to a device_node's pci_dn */ |
| @@ -128,9 +210,6 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) | |||
| 128 | /** Find the bus corresponding to the indicated device node */ | 210 | /** Find the bus corresponding to the indicated device node */ |
| 129 | struct pci_bus * pcibios_find_pci_bus(struct device_node *dn); | 211 | struct pci_bus * pcibios_find_pci_bus(struct device_node *dn); |
| 130 | 212 | ||
| 131 | extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||
| 132 | struct device_node *dev, int primary); | ||
| 133 | |||
| 134 | /** Remove all of the PCI devices under this bus */ | 213 | /** Remove all of the PCI devices under this bus */ |
| 135 | void pcibios_remove_pci_devices(struct pci_bus *bus); | 214 | void pcibios_remove_pci_devices(struct pci_bus *bus); |
| 136 | 215 | ||
| @@ -148,13 +227,38 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) | |||
| 148 | return PCI_DN(busdn)->phb; | 227 | return PCI_DN(busdn)->phb; |
| 149 | } | 228 | } |
| 150 | 229 | ||
| 230 | extern void pcibios_free_controller(struct pci_controller *phb); | ||
| 231 | |||
| 232 | extern void isa_bridge_find_early(struct pci_controller *hose); | ||
| 233 | |||
| 234 | extern int pcibios_unmap_io_space(struct pci_bus *bus); | ||
| 235 | extern int pcibios_map_io_space(struct pci_bus *bus); | ||
| 236 | |||
| 237 | /* Return values for ppc_md.pci_probe_mode function */ | ||
| 238 | #define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ | ||
| 239 | #define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ | ||
| 240 | #define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ | ||
| 241 | |||
| 242 | #ifdef CONFIG_NUMA | ||
| 243 | #define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) | ||
| 244 | #else | ||
| 245 | #define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1) | ||
| 246 | #endif | ||
| 247 | |||
| 248 | #endif /* CONFIG_PPC64 */ | ||
| 249 | |||
| 250 | /* Get the PCI host controller for an OF device */ | ||
| 151 | extern struct pci_controller* | 251 | extern struct pci_controller* |
| 152 | pci_find_hose_for_OF_device(struct device_node* node); | 252 | pci_find_hose_for_OF_device(struct device_node* node); |
| 153 | 253 | ||
| 254 | /* Fill up host controller resources from the OF node */ | ||
| 255 | extern void | ||
| 256 | pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||
| 257 | struct device_node *dev, int primary); | ||
| 258 | |||
| 259 | /* Allocate a new PCI host bridge structure */ | ||
| 154 | extern struct pci_controller * | 260 | extern struct pci_controller * |
| 155 | pcibios_alloc_controller(struct device_node *dev); | 261 | pcibios_alloc_controller(struct device_node *dev); |
| 156 | extern void pcibios_free_controller(struct pci_controller *phb); | ||
| 157 | |||
| 158 | #ifdef CONFIG_PCI | 262 | #ifdef CONFIG_PCI |
| 159 | extern unsigned long pci_address_to_pio(phys_addr_t address); | 263 | extern unsigned long pci_address_to_pio(phys_addr_t address); |
| 160 | #else | 264 | #else |
| @@ -164,17 +268,7 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address) | |||
| 164 | } | 268 | } |
| 165 | #endif | 269 | #endif |
| 166 | 270 | ||
| 167 | /* Return values for ppc_md.pci_probe_mode function */ | ||
| 168 | #define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ | ||
| 169 | #define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ | ||
| 170 | #define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ | ||
| 171 | 271 | ||
| 172 | #ifdef CONFIG_NUMA | ||
| 173 | #define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) | ||
| 174 | #else | ||
| 175 | #define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1) | ||
| 176 | #endif | ||
| 177 | 272 | ||
| 178 | #endif /* CONFIG_PPC64 */ | ||
| 179 | #endif /* __KERNEL__ */ | 273 | #endif /* __KERNEL__ */ |
| 180 | #endif | 274 | #endif |
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index ce0f13e8eb14..0cd3e77efd20 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h | |||
| @@ -107,8 +107,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, | |||
| 107 | #define get_pci_dma_ops() NULL | 107 | #define get_pci_dma_ops() NULL |
| 108 | #endif | 108 | #endif |
| 109 | 109 | ||
| 110 | extern int pci_domain_nr(struct pci_bus *bus); | ||
| 111 | |||
| 112 | /* Decide whether to display the domain number in /proc */ | 110 | /* Decide whether to display the domain number in /proc */ |
| 113 | extern int pci_proc_domain(struct pci_bus *bus); | 111 | extern int pci_proc_domain(struct pci_bus *bus); |
| 114 | 112 | ||
| @@ -130,9 +128,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, | |||
| 130 | */ | 128 | */ |
| 131 | #define pci_dac_dma_supported(pci_dev, mask) (0) | 129 | #define pci_dac_dma_supported(pci_dev, mask) (0) |
| 132 | 130 | ||
| 133 | /* Return the index of the PCI controller for device PDEV. */ | ||
| 134 | #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index | ||
| 135 | |||
| 136 | /* Set the name of the bus as it appears in /proc/bus/pci */ | 131 | /* Set the name of the bus as it appears in /proc/bus/pci */ |
| 137 | static inline int pci_proc_domain(struct pci_bus *bus) | 132 | static inline int pci_proc_domain(struct pci_bus *bus) |
| 138 | { | 133 | { |
| @@ -141,6 +136,8 @@ static inline int pci_proc_domain(struct pci_bus *bus) | |||
| 141 | 136 | ||
| 142 | #endif /* CONFIG_PPC64 */ | 137 | #endif /* CONFIG_PPC64 */ |
| 143 | 138 | ||
| 139 | extern int pci_domain_nr(struct pci_bus *bus); | ||
| 140 | |||
| 144 | struct vm_area_struct; | 141 | struct vm_area_struct; |
| 145 | /* Map a range of PCI memory or I/O space for a device into user space */ | 142 | /* Map a range of PCI memory or I/O space for a device into user space */ |
| 146 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | 143 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, |
| @@ -220,10 +217,6 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev, | |||
| 220 | return root; | 217 | return root; |
| 221 | } | 218 | } |
| 222 | 219 | ||
| 223 | extern int unmap_bus_range(struct pci_bus *bus); | ||
| 224 | |||
| 225 | extern int remap_bus_range(struct pci_bus *bus); | ||
| 226 | |||
| 227 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, | 220 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, |
| 228 | struct pci_bus *bus); | 221 | struct pci_bus *bus); |
| 229 | 222 | ||
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h index 7fb730c62f83..b2b880a6f631 100644 --- a/include/asm-powerpc/pgtable-ppc32.h +++ b/include/asm-powerpc/pgtable-ppc32.h | |||
| @@ -6,11 +6,7 @@ | |||
| 6 | #ifndef __ASSEMBLY__ | 6 | #ifndef __ASSEMBLY__ |
| 7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
| 8 | #include <linux/threads.h> | 8 | #include <linux/threads.h> |
| 9 | #include <asm/processor.h> /* For TASK_SIZE */ | ||
| 10 | #include <asm/mmu.h> | ||
| 11 | #include <asm/page.h> | ||
| 12 | #include <asm/io.h> /* For sub-arch specific PPC_PIN_SIZE */ | 9 | #include <asm/io.h> /* For sub-arch specific PPC_PIN_SIZE */ |
| 13 | struct mm_struct; | ||
| 14 | 10 | ||
| 15 | extern unsigned long va_to_phys(unsigned long address); | 11 | extern unsigned long va_to_phys(unsigned long address); |
| 16 | extern pte_t *va_to_pte(unsigned long address); | 12 | extern pte_t *va_to_pte(unsigned long address); |
| @@ -488,14 +484,6 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
| 488 | #define pfn_pte(pfn, prot) __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\ | 484 | #define pfn_pte(pfn, prot) __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\ |
| 489 | pgprot_val(prot)) | 485 | pgprot_val(prot)) |
| 490 | #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) | 486 | #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) |
| 491 | |||
| 492 | /* | ||
| 493 | * ZERO_PAGE is a global shared page that is always zero: used | ||
| 494 | * for zero-mapped memory areas etc.. | ||
| 495 | */ | ||
| 496 | extern unsigned long empty_zero_page[1024]; | ||
| 497 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | ||
| 498 | |||
| 499 | #endif /* __ASSEMBLY__ */ | 487 | #endif /* __ASSEMBLY__ */ |
| 500 | 488 | ||
| 501 | #define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0) | 489 | #define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0) |
| @@ -734,10 +722,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
| 734 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) | 722 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) |
| 735 | #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) | 723 | #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) |
| 736 | 724 | ||
| 737 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
| 738 | |||
| 739 | extern void paging_init(void); | ||
| 740 | |||
| 741 | /* | 725 | /* |
| 742 | * Encode and decode a swap entry. | 726 | * Encode and decode a swap entry. |
| 743 | * Note that the bits we use in a PTE for representing a swap entry | 727 | * Note that the bits we use in a PTE for representing a swap entry |
| @@ -755,40 +739,6 @@ extern void paging_init(void); | |||
| 755 | #define pte_to_pgoff(pte) (pte_val(pte) >> 3) | 739 | #define pte_to_pgoff(pte) (pte_val(pte) >> 3) |
| 756 | #define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE }) | 740 | #define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE }) |
| 757 | 741 | ||
| 758 | /* CONFIG_APUS */ | ||
| 759 | /* For virtual address to physical address conversion */ | ||
| 760 | extern void cache_clear(__u32 addr, int length); | ||
| 761 | extern void cache_push(__u32 addr, int length); | ||
| 762 | extern int mm_end_of_chunk (unsigned long addr, int len); | ||
| 763 | extern unsigned long iopa(unsigned long addr); | ||
| 764 | extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; | ||
| 765 | |||
| 766 | /* Values for nocacheflag and cmode */ | ||
| 767 | /* These are not used by the APUS kernel_map, but prevents | ||
| 768 | compilation errors. */ | ||
| 769 | #define KERNELMAP_FULL_CACHING 0 | ||
| 770 | #define KERNELMAP_NOCACHE_SER 1 | ||
| 771 | #define KERNELMAP_NOCACHE_NONSER 2 | ||
| 772 | #define KERNELMAP_NO_COPYBACK 3 | ||
| 773 | |||
| 774 | /* | ||
| 775 | * Map some physical address range into the kernel address space. | ||
| 776 | */ | ||
| 777 | extern unsigned long kernel_map(unsigned long paddr, unsigned long size, | ||
| 778 | int nocacheflag, unsigned long *memavailp ); | ||
| 779 | |||
| 780 | /* | ||
| 781 | * Set cache mode of (kernel space) address range. | ||
| 782 | */ | ||
| 783 | extern void kernel_set_cachemode (unsigned long address, unsigned long size, | ||
| 784 | unsigned int cmode); | ||
| 785 | |||
| 786 | /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ | ||
| 787 | #define kern_addr_valid(addr) (1) | ||
| 788 | |||
| 789 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
| 790 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
| 791 | |||
| 792 | /* | 742 | /* |
| 793 | * No page table caches to initialise | 743 | * No page table caches to initialise |
| 794 | */ | 744 | */ |
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index 3cfd98f44bfe..4ea99922a75c 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h | |||
| @@ -7,11 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #ifndef __ASSEMBLY__ | 8 | #ifndef __ASSEMBLY__ |
| 9 | #include <linux/stddef.h> | 9 | #include <linux/stddef.h> |
| 10 | #include <asm/processor.h> /* For TASK_SIZE */ | ||
| 11 | #include <asm/mmu.h> | ||
| 12 | #include <asm/page.h> | ||
| 13 | #include <asm/tlbflush.h> | 10 | #include <asm/tlbflush.h> |
| 14 | struct mm_struct; | ||
| 15 | #endif /* __ASSEMBLY__ */ | 11 | #endif /* __ASSEMBLY__ */ |
| 16 | 12 | ||
| 17 | #ifdef CONFIG_PPC_64K_PAGES | 13 | #ifdef CONFIG_PPC_64K_PAGES |
| @@ -27,7 +23,7 @@ struct mm_struct; | |||
| 27 | */ | 23 | */ |
| 28 | #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ | 24 | #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ |
| 29 | PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT) | 25 | PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT) |
| 30 | #define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE) | 26 | #define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE) |
| 31 | 27 | ||
| 32 | #if TASK_SIZE_USER64 > PGTABLE_RANGE | 28 | #if TASK_SIZE_USER64 > PGTABLE_RANGE |
| 33 | #error TASK_SIZE_USER64 exceeds pagetable range | 29 | #error TASK_SIZE_USER64 exceeds pagetable range |
| @@ -37,19 +33,28 @@ struct mm_struct; | |||
| 37 | #error TASK_SIZE_USER64 exceeds user VSID range | 33 | #error TASK_SIZE_USER64 exceeds user VSID range |
| 38 | #endif | 34 | #endif |
| 39 | 35 | ||
| 36 | |||
| 40 | /* | 37 | /* |
| 41 | * Define the address range of the vmalloc VM area. | 38 | * Define the address range of the vmalloc VM area. |
| 42 | */ | 39 | */ |
| 43 | #define VMALLOC_START ASM_CONST(0xD000000000000000) | 40 | #define VMALLOC_START ASM_CONST(0xD000000000000000) |
| 44 | #define VMALLOC_SIZE ASM_CONST(0x80000000000) | 41 | #define VMALLOC_SIZE (PGTABLE_RANGE >> 1) |
| 45 | #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) | 42 | #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) |
| 46 | 43 | ||
| 47 | /* | 44 | /* |
| 48 | * Define the address range of the imalloc VM area. | 45 | * Define the address ranges for MMIO and IO space : |
| 46 | * | ||
| 47 | * ISA_IO_BASE = VMALLOC_END, 64K reserved area | ||
| 48 | * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces | ||
| 49 | * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE | ||
| 49 | */ | 50 | */ |
| 50 | #define PHBS_IO_BASE VMALLOC_END | 51 | #define FULL_IO_SIZE 0x80000000ul |
| 51 | #define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */ | 52 | #define ISA_IO_BASE (VMALLOC_END) |
| 52 | #define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE) | 53 | #define ISA_IO_END (VMALLOC_END + 0x10000ul) |
| 54 | #define PHB_IO_BASE (ISA_IO_END) | ||
| 55 | #define PHB_IO_END (VMALLOC_END + FULL_IO_SIZE) | ||
| 56 | #define IOREMAP_BASE (PHB_IO_END) | ||
| 57 | #define IOREMAP_END (VMALLOC_START + PGTABLE_RANGE) | ||
| 53 | 58 | ||
| 54 | /* | 59 | /* |
| 55 | * Region IDs | 60 | * Region IDs |
| @@ -134,16 +139,6 @@ struct mm_struct; | |||
| 134 | #define __S110 PAGE_SHARED_X | 139 | #define __S110 PAGE_SHARED_X |
| 135 | #define __S111 PAGE_SHARED_X | 140 | #define __S111 PAGE_SHARED_X |
| 136 | 141 | ||
| 137 | #ifndef __ASSEMBLY__ | ||
| 138 | |||
| 139 | /* | ||
| 140 | * ZERO_PAGE is a global shared page that is always zero: used | ||
| 141 | * for zero-mapped memory areas etc.. | ||
| 142 | */ | ||
| 143 | extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; | ||
| 144 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | ||
| 145 | #endif /* __ASSEMBLY__ */ | ||
| 146 | |||
| 147 | #ifdef CONFIG_HUGETLB_PAGE | 142 | #ifdef CONFIG_HUGETLB_PAGE |
| 148 | 143 | ||
| 149 | #define HAVE_ARCH_UNMAPPED_AREA | 144 | #define HAVE_ARCH_UNMAPPED_AREA |
| @@ -442,10 +437,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
| 442 | #define pgd_ERROR(e) \ | 437 | #define pgd_ERROR(e) \ |
| 443 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) | 438 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) |
| 444 | 439 | ||
| 445 | extern pgd_t swapper_pg_dir[]; | ||
| 446 | |||
| 447 | extern void paging_init(void); | ||
| 448 | |||
| 449 | /* Encode and de-code a swap entry */ | 440 | /* Encode and de-code a swap entry */ |
| 450 | #define __swp_type(entry) (((entry).val >> 1) & 0x3f) | 441 | #define __swp_type(entry) (((entry).val >> 1) & 0x3f) |
| 451 | #define __swp_offset(entry) ((entry).val >> 8) | 442 | #define __swp_offset(entry) ((entry).val >> 8) |
| @@ -456,17 +447,6 @@ extern void paging_init(void); | |||
| 456 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) | 447 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) |
| 457 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) | 448 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) |
| 458 | 449 | ||
| 459 | /* | ||
| 460 | * kern_addr_valid is intended to indicate whether an address is a valid | ||
| 461 | * kernel address. Most 32-bit archs define it as always true (like this) | ||
| 462 | * but most 64-bit archs actually perform a test. What should we do here? | ||
| 463 | * The only use is in fs/ncpfs/dir.c | ||
| 464 | */ | ||
| 465 | #define kern_addr_valid(addr) (1) | ||
| 466 | |||
| 467 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
| 468 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
| 469 | |||
| 470 | void pgtable_cache_init(void); | 450 | void pgtable_cache_init(void); |
| 471 | 451 | ||
| 472 | /* | 452 | /* |
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index 78bf4ae712a6..d18ffe7bc7c4 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h | |||
| @@ -2,6 +2,13 @@ | |||
| 2 | #define _ASM_POWERPC_PGTABLE_H | 2 | #define _ASM_POWERPC_PGTABLE_H |
| 3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
| 4 | 4 | ||
| 5 | #ifndef __ASSEMBLY__ | ||
| 6 | #include <asm/processor.h> /* For TASK_SIZE */ | ||
| 7 | #include <asm/mmu.h> | ||
| 8 | #include <asm/page.h> | ||
| 9 | struct mm_struct; | ||
| 10 | #endif /* !__ASSEMBLY__ */ | ||
| 11 | |||
| 5 | #if defined(CONFIG_PPC64) | 12 | #if defined(CONFIG_PPC64) |
| 6 | # include <asm/pgtable-ppc64.h> | 13 | # include <asm/pgtable-ppc64.h> |
| 7 | #else | 14 | #else |
| @@ -9,6 +16,27 @@ | |||
| 9 | #endif | 16 | #endif |
| 10 | 17 | ||
| 11 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
| 19 | /* | ||
| 20 | * ZERO_PAGE is a global shared page that is always zero: used | ||
| 21 | * for zero-mapped memory areas etc.. | ||
| 22 | */ | ||
| 23 | extern unsigned long empty_zero_page[]; | ||
| 24 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | ||
| 25 | |||
| 26 | extern pgd_t swapper_pg_dir[]; | ||
| 27 | |||
| 28 | extern void paging_init(void); | ||
| 29 | |||
| 30 | /* | ||
| 31 | * kern_addr_valid is intended to indicate whether an address is a valid | ||
| 32 | * kernel address. Most 32-bit archs define it as always true (like this) | ||
| 33 | * but most 64-bit archs actually perform a test. What should we do here? | ||
| 34 | */ | ||
| 35 | #define kern_addr_valid(addr) (1) | ||
| 36 | |||
| 37 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
| 38 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
| 39 | |||
| 12 | #include <asm-generic/pgtable.h> | 40 | #include <asm-generic/pgtable.h> |
| 13 | #endif /* __ASSEMBLY__ */ | 41 | #endif /* __ASSEMBLY__ */ |
| 14 | 42 | ||
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 8e2005159ffd..b847aa10074b 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h | |||
| @@ -26,7 +26,7 @@ extern int global_phb_number; | |||
| 26 | 26 | ||
| 27 | extern void find_and_init_phbs(void); | 27 | extern void find_and_init_phbs(void); |
| 28 | 28 | ||
| 29 | extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ | 29 | extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ |
| 30 | 30 | ||
| 31 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ | 31 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ |
| 32 | #define BUID_HI(buid) ((buid) >> 32) | 32 | #define BUID_HI(buid) ((buid) >> 32) |
| @@ -47,8 +47,8 @@ extern void init_pci_config_tokens (void); | |||
| 47 | extern unsigned long get_phb_buid (struct device_node *); | 47 | extern unsigned long get_phb_buid (struct device_node *); |
| 48 | extern int rtas_setup_phb(struct pci_controller *phb); | 48 | extern int rtas_setup_phb(struct pci_controller *phb); |
| 49 | 49 | ||
| 50 | /* From pSeries_pci.h */ | 50 | /* From iSeries PCI */ |
| 51 | extern void pSeries_final_fixup(void); | 51 | extern void iSeries_pcibios_init(void); |
| 52 | 52 | ||
| 53 | extern unsigned long pci_probe_only; | 53 | extern unsigned long pci_probe_only; |
| 54 | 54 | ||
| @@ -139,6 +139,9 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag); | |||
| 139 | */ | 139 | */ |
| 140 | struct device_node * find_device_pe(struct device_node *dn); | 140 | struct device_node * find_device_pe(struct device_node *dn); |
| 141 | 141 | ||
| 142 | void eeh_sysfs_add_device(struct pci_dev *pdev); | ||
| 143 | void eeh_sysfs_remove_device(struct pci_dev *pdev); | ||
| 144 | |||
| 142 | #endif /* CONFIG_EEH */ | 145 | #endif /* CONFIG_EEH */ |
| 143 | 146 | ||
| 144 | #else /* CONFIG_PCI */ | 147 | #else /* CONFIG_PCI */ |
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index d947b1609491..e28b10805159 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h | |||
| @@ -43,14 +43,6 @@ extern int _chrp_type; | |||
| 43 | /* what kind of prep workstation we are */ | 43 | /* what kind of prep workstation we are */ |
| 44 | extern int _prep_type; | 44 | extern int _prep_type; |
| 45 | 45 | ||
| 46 | /* | ||
| 47 | * This is used to identify the board type from a given PReP board | ||
| 48 | * vendor. Board revision is also made available. This will be moved | ||
| 49 | * elsewhere soon | ||
| 50 | */ | ||
| 51 | extern unsigned char ucBoardRev; | ||
| 52 | extern unsigned char ucBoardRevMaj, ucBoardRevMin; | ||
| 53 | |||
| 54 | #endif /* CONFIG_PPC_PREP */ | 46 | #endif /* CONFIG_PPC_PREP */ |
| 55 | 47 | ||
| 56 | #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ | 48 | #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 6845af93ba91..1632baa17dc6 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
| @@ -98,10 +98,19 @@ struct device_node { | |||
| 98 | extern struct device_node *of_chosen; | 98 | extern struct device_node *of_chosen; |
| 99 | 99 | ||
| 100 | /* flag descriptions */ | 100 | /* flag descriptions */ |
| 101 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ | 101 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ |
| 102 | #define OF_DETACHED 2 /* node has been detached from the device tree */ | ||
| 103 | |||
| 104 | static inline int of_node_check_flag(struct device_node *n, unsigned long flag) | ||
| 105 | { | ||
| 106 | return test_bit(flag, &n->_flags); | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline void of_node_set_flag(struct device_node *n, unsigned long flag) | ||
| 110 | { | ||
| 111 | set_bit(flag, &n->_flags); | ||
| 112 | } | ||
| 102 | 113 | ||
| 103 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) | ||
| 104 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) | ||
| 105 | 114 | ||
| 106 | #define HAVE_ARCH_DEVTREE_FIXUPS | 115 | #define HAVE_ARCH_DEVTREE_FIXUPS |
| 107 | 116 | ||
| @@ -124,6 +133,9 @@ extern struct device_node *of_find_node_by_type(struct device_node *from, | |||
| 124 | dn = of_find_node_by_type(dn, type)) | 133 | dn = of_find_node_by_type(dn, type)) |
| 125 | extern struct device_node *of_find_compatible_node(struct device_node *from, | 134 | extern struct device_node *of_find_compatible_node(struct device_node *from, |
| 126 | const char *type, const char *compat); | 135 | const char *type, const char *compat); |
| 136 | #define for_each_compatible_node(dn, type, compatible) \ | ||
| 137 | for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ | ||
| 138 | dn = of_find_compatible_node(dn, type, compatible)) | ||
| 127 | extern struct device_node *of_find_node_by_path(const char *path); | 139 | extern struct device_node *of_find_node_by_path(const char *path); |
| 128 | extern struct device_node *of_find_node_by_phandle(phandle handle); | 140 | extern struct device_node *of_find_node_by_phandle(phandle handle); |
| 129 | extern struct device_node *of_find_all_nodes(struct device_node *prev); | 141 | extern struct device_node *of_find_all_nodes(struct device_node *prev); |
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h index 1e04651eedc4..a6f3f5ee7ca7 100644 --- a/include/asm-powerpc/ps3.h +++ b/include/asm-powerpc/ps3.h | |||
| @@ -35,7 +35,8 @@ union ps3_firmware_version { | |||
| 35 | }; | 35 | }; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | int ps3_get_firmware_version(union ps3_firmware_version *v); | 38 | void ps3_get_firmware_version(union ps3_firmware_version *v); |
| 39 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev); | ||
| 39 | 40 | ||
| 40 | /* 'Other OS' area */ | 41 | /* 'Other OS' area */ |
| 41 | 42 | ||
| @@ -48,18 +49,6 @@ enum ps3_param_av_multi_out { | |||
| 48 | 49 | ||
| 49 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); | 50 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); |
| 50 | 51 | ||
| 51 | /** | ||
| 52 | * struct ps3_device_id - HV bus device identifier from the system repository | ||
| 53 | * @bus_id: HV bus id, {1..} (zero invalid) | ||
| 54 | * @dev_id: HV device id, {0..} | ||
| 55 | */ | ||
| 56 | |||
| 57 | struct ps3_device_id { | ||
| 58 | unsigned int bus_id; | ||
| 59 | unsigned int dev_id; | ||
| 60 | }; | ||
| 61 | |||
| 62 | |||
| 63 | /* dma routines */ | 52 | /* dma routines */ |
| 64 | 53 | ||
| 65 | enum ps3_dma_page_size { | 54 | enum ps3_dma_page_size { |
| @@ -74,6 +63,8 @@ enum ps3_dma_region_type { | |||
| 74 | PS3_DMA_INTERNAL = 2, | 63 | PS3_DMA_INTERNAL = 2, |
| 75 | }; | 64 | }; |
| 76 | 65 | ||
| 66 | struct ps3_dma_region_ops; | ||
| 67 | |||
| 77 | /** | 68 | /** |
| 78 | * struct ps3_dma_region - A per device dma state variables structure | 69 | * struct ps3_dma_region - A per device dma state variables structure |
| 79 | * @did: The HV device id. | 70 | * @did: The HV device id. |
| @@ -81,21 +72,42 @@ enum ps3_dma_region_type { | |||
| 81 | * @region_type: The HV region type. | 72 | * @region_type: The HV region type. |
| 82 | * @bus_addr: The 'translated' bus address of the region. | 73 | * @bus_addr: The 'translated' bus address of the region. |
| 83 | * @len: The length in bytes of the region. | 74 | * @len: The length in bytes of the region. |
| 75 | * @offset: The offset from the start of memory of the region. | ||
| 76 | * @ioid: The IOID of the device who owns this region | ||
| 84 | * @chunk_list: Opaque variable used by the ioc page manager. | 77 | * @chunk_list: Opaque variable used by the ioc page manager. |
| 78 | * @region_ops: struct ps3_dma_region_ops - dma region operations | ||
| 85 | */ | 79 | */ |
| 86 | 80 | ||
| 87 | struct ps3_dma_region { | 81 | struct ps3_dma_region { |
| 88 | struct ps3_device_id did; | 82 | struct ps3_system_bus_device *dev; |
| 83 | /* device variables */ | ||
| 84 | const struct ps3_dma_region_ops *region_ops; | ||
| 85 | unsigned char ioid; | ||
| 89 | enum ps3_dma_page_size page_size; | 86 | enum ps3_dma_page_size page_size; |
| 90 | enum ps3_dma_region_type region_type; | 87 | enum ps3_dma_region_type region_type; |
| 91 | unsigned long bus_addr; | ||
| 92 | unsigned long len; | 88 | unsigned long len; |
| 89 | unsigned long offset; | ||
| 90 | |||
| 91 | /* driver variables (set by ps3_dma_region_create) */ | ||
| 92 | unsigned long bus_addr; | ||
| 93 | struct { | 93 | struct { |
| 94 | spinlock_t lock; | 94 | spinlock_t lock; |
| 95 | struct list_head head; | 95 | struct list_head head; |
| 96 | } chunk_list; | 96 | } chunk_list; |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | struct ps3_dma_region_ops { | ||
| 100 | int (*create)(struct ps3_dma_region *); | ||
| 101 | int (*free)(struct ps3_dma_region *); | ||
| 102 | int (*map)(struct ps3_dma_region *, | ||
| 103 | unsigned long virt_addr, | ||
| 104 | unsigned long len, | ||
| 105 | unsigned long *bus_addr, | ||
| 106 | u64 iopte_pp); | ||
| 107 | int (*unmap)(struct ps3_dma_region *, | ||
| 108 | unsigned long bus_addr, | ||
| 109 | unsigned long len); | ||
| 110 | }; | ||
| 99 | /** | 111 | /** |
| 100 | * struct ps3_dma_region_init - Helper to initialize structure variables | 112 | * struct ps3_dma_region_init - Helper to initialize structure variables |
| 101 | * | 113 | * |
| @@ -103,18 +115,16 @@ struct ps3_dma_region { | |||
| 103 | * ps3_system_bus_device_register. | 115 | * ps3_system_bus_device_register. |
| 104 | */ | 116 | */ |
| 105 | 117 | ||
| 106 | static inline void ps3_dma_region_init(struct ps3_dma_region *r, | 118 | struct ps3_system_bus_device; |
| 107 | const struct ps3_device_id* did, enum ps3_dma_page_size page_size, | 119 | |
| 108 | enum ps3_dma_region_type region_type) | 120 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, |
| 109 | { | 121 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, |
| 110 | r->did = *did; | 122 | enum ps3_dma_region_type region_type, void *addr, unsigned long len); |
| 111 | r->page_size = page_size; | ||
| 112 | r->region_type = region_type; | ||
| 113 | } | ||
| 114 | int ps3_dma_region_create(struct ps3_dma_region *r); | 123 | int ps3_dma_region_create(struct ps3_dma_region *r); |
| 115 | int ps3_dma_region_free(struct ps3_dma_region *r); | 124 | int ps3_dma_region_free(struct ps3_dma_region *r); |
| 116 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | 125 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, |
| 117 | unsigned long len, unsigned long *bus_addr); | 126 | unsigned long len, unsigned long *bus_addr, |
| 127 | u64 iopte_pp); | ||
| 118 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | 128 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, |
| 119 | unsigned long len); | 129 | unsigned long len); |
| 120 | 130 | ||
| @@ -125,6 +135,7 @@ enum ps3_mmio_page_size { | |||
| 125 | PS3_MMIO_64K = 16U | 135 | PS3_MMIO_64K = 16U |
| 126 | }; | 136 | }; |
| 127 | 137 | ||
| 138 | struct ps3_mmio_region_ops; | ||
| 128 | /** | 139 | /** |
| 129 | * struct ps3_mmio_region - a per device mmio state variables structure | 140 | * struct ps3_mmio_region - a per device mmio state variables structure |
| 130 | * | 141 | * |
| @@ -132,13 +143,18 @@ enum ps3_mmio_page_size { | |||
| 132 | */ | 143 | */ |
| 133 | 144 | ||
| 134 | struct ps3_mmio_region { | 145 | struct ps3_mmio_region { |
| 135 | struct ps3_device_id did; | 146 | struct ps3_system_bus_device *dev; |
| 147 | const struct ps3_mmio_region_ops *mmio_ops; | ||
| 136 | unsigned long bus_addr; | 148 | unsigned long bus_addr; |
| 137 | unsigned long len; | 149 | unsigned long len; |
| 138 | enum ps3_mmio_page_size page_size; | 150 | enum ps3_mmio_page_size page_size; |
| 139 | unsigned long lpar_addr; | 151 | unsigned long lpar_addr; |
| 140 | }; | 152 | }; |
| 141 | 153 | ||
| 154 | struct ps3_mmio_region_ops { | ||
| 155 | int (*create)(struct ps3_mmio_region *); | ||
| 156 | int (*free)(struct ps3_mmio_region *); | ||
| 157 | }; | ||
| 142 | /** | 158 | /** |
| 143 | * struct ps3_mmio_region_init - Helper to initialize structure variables | 159 | * struct ps3_mmio_region_init - Helper to initialize structure variables |
| 144 | * | 160 | * |
| @@ -146,15 +162,9 @@ struct ps3_mmio_region { | |||
| 146 | * ps3_system_bus_device_register. | 162 | * ps3_system_bus_device_register. |
| 147 | */ | 163 | */ |
| 148 | 164 | ||
| 149 | static inline void ps3_mmio_region_init(struct ps3_mmio_region *r, | 165 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, |
| 150 | const struct ps3_device_id* did, unsigned long bus_addr, | 166 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, |
| 151 | unsigned long len, enum ps3_mmio_page_size page_size) | 167 | enum ps3_mmio_page_size page_size); |
| 152 | { | ||
| 153 | r->did = *did; | ||
| 154 | r->bus_addr = bus_addr; | ||
| 155 | r->len = len; | ||
| 156 | r->page_size = page_size; | ||
| 157 | } | ||
| 158 | int ps3_mmio_region_create(struct ps3_mmio_region *r); | 168 | int ps3_mmio_region_create(struct ps3_mmio_region *r); |
| 159 | int ps3_free_mmio_region(struct ps3_mmio_region *r); | 169 | int ps3_free_mmio_region(struct ps3_mmio_region *r); |
| 160 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); | 170 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); |
| @@ -187,11 +197,10 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, | |||
| 187 | unsigned int class, unsigned int *virq); | 197 | unsigned int class, unsigned int *virq); |
| 188 | int ps3_spe_irq_destroy(unsigned int virq); | 198 | int ps3_spe_irq_destroy(unsigned int virq); |
| 189 | 199 | ||
| 190 | int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | 200 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, |
| 191 | const struct ps3_device_id *did, unsigned int interrupt_id, | 201 | enum ps3_cpu_binding cpu, unsigned int *virq); |
| 192 | unsigned int *virq); | 202 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, |
| 193 | int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | 203 | unsigned int virq); |
| 194 | unsigned int interrupt_id, unsigned int virq); | ||
| 195 | 204 | ||
| 196 | /* lv1 result codes */ | 205 | /* lv1 result codes */ |
| 197 | 206 | ||
| @@ -289,11 +298,33 @@ static inline const char* ps3_result(int result) | |||
| 289 | /* system bus routines */ | 298 | /* system bus routines */ |
| 290 | 299 | ||
| 291 | enum ps3_match_id { | 300 | enum ps3_match_id { |
| 292 | PS3_MATCH_ID_EHCI = 1, | 301 | PS3_MATCH_ID_EHCI = 1, |
| 293 | PS3_MATCH_ID_OHCI, | 302 | PS3_MATCH_ID_OHCI = 2, |
| 294 | PS3_MATCH_ID_GELIC, | 303 | PS3_MATCH_ID_GELIC = 3, |
| 295 | PS3_MATCH_ID_AV_SETTINGS, | 304 | PS3_MATCH_ID_AV_SETTINGS = 4, |
| 296 | PS3_MATCH_ID_SYSTEM_MANAGER, | 305 | PS3_MATCH_ID_SYSTEM_MANAGER = 5, |
| 306 | PS3_MATCH_ID_STOR_DISK = 6, | ||
| 307 | PS3_MATCH_ID_STOR_ROM = 7, | ||
| 308 | PS3_MATCH_ID_STOR_FLASH = 8, | ||
| 309 | PS3_MATCH_ID_SOUND = 9, | ||
| 310 | PS3_MATCH_ID_GRAPHICS = 10, | ||
| 311 | }; | ||
| 312 | |||
| 313 | #define PS3_MODULE_ALIAS_EHCI "ps3:1" | ||
| 314 | #define PS3_MODULE_ALIAS_OHCI "ps3:2" | ||
| 315 | #define PS3_MODULE_ALIAS_GELIC "ps3:3" | ||
| 316 | #define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4" | ||
| 317 | #define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5" | ||
| 318 | #define PS3_MODULE_ALIAS_STOR_DISK "ps3:6" | ||
| 319 | #define PS3_MODULE_ALIAS_STOR_ROM "ps3:7" | ||
| 320 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8" | ||
| 321 | #define PS3_MODULE_ALIAS_SOUND "ps3:9" | ||
| 322 | #define PS3_MODULE_ALIAS_GRAPHICS "ps3:10" | ||
| 323 | |||
| 324 | enum ps3_system_bus_device_type { | ||
| 325 | PS3_DEVICE_TYPE_IOC0 = 1, | ||
| 326 | PS3_DEVICE_TYPE_SB, | ||
| 327 | PS3_DEVICE_TYPE_VUART, | ||
| 297 | }; | 328 | }; |
| 298 | 329 | ||
| 299 | /** | 330 | /** |
| @@ -302,14 +333,23 @@ enum ps3_match_id { | |||
| 302 | 333 | ||
| 303 | struct ps3_system_bus_device { | 334 | struct ps3_system_bus_device { |
| 304 | enum ps3_match_id match_id; | 335 | enum ps3_match_id match_id; |
| 305 | struct ps3_device_id did; | 336 | enum ps3_system_bus_device_type dev_type; |
| 306 | unsigned int interrupt_id; | 337 | |
| 307 | /* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */ | 338 | unsigned int bus_id; /* SB */ |
| 308 | struct ps3_dma_region *d_region; | 339 | unsigned int dev_id; /* SB */ |
| 309 | struct ps3_mmio_region *m_region; | 340 | unsigned int interrupt_id; /* SB */ |
| 341 | struct ps3_dma_region *d_region; /* SB, IOC0 */ | ||
| 342 | struct ps3_mmio_region *m_region; /* SB, IOC0*/ | ||
| 343 | unsigned int port_number; /* VUART */ | ||
| 344 | |||
| 345 | /* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */ | ||
| 310 | struct device core; | 346 | struct device core; |
| 347 | void *driver_priv; /* private driver variables */ | ||
| 311 | }; | 348 | }; |
| 312 | 349 | ||
| 350 | int ps3_open_hv_device(struct ps3_system_bus_device *dev); | ||
| 351 | int ps3_close_hv_device(struct ps3_system_bus_device *dev); | ||
| 352 | |||
| 313 | /** | 353 | /** |
| 314 | * struct ps3_system_bus_driver - a driver for a device on the system bus | 354 | * struct ps3_system_bus_driver - a driver for a device on the system bus |
| 315 | */ | 355 | */ |
| @@ -319,6 +359,7 @@ struct ps3_system_bus_driver { | |||
| 319 | struct device_driver core; | 359 | struct device_driver core; |
| 320 | int (*probe)(struct ps3_system_bus_device *); | 360 | int (*probe)(struct ps3_system_bus_device *); |
| 321 | int (*remove)(struct ps3_system_bus_device *); | 361 | int (*remove)(struct ps3_system_bus_device *); |
| 362 | int (*shutdown)(struct ps3_system_bus_device *); | ||
| 322 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ | 363 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ |
| 323 | /* int (*resume)(struct ps3_system_bus_device *); */ | 364 | /* int (*resume)(struct ps3_system_bus_device *); */ |
| 324 | }; | 365 | }; |
| @@ -326,16 +367,24 @@ struct ps3_system_bus_driver { | |||
| 326 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); | 367 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); |
| 327 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); | 368 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); |
| 328 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); | 369 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); |
| 329 | static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver( | 370 | |
| 371 | static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( | ||
| 330 | struct device_driver *_drv) | 372 | struct device_driver *_drv) |
| 331 | { | 373 | { |
| 332 | return container_of(_drv, struct ps3_system_bus_driver, core); | 374 | return container_of(_drv, struct ps3_system_bus_driver, core); |
| 333 | } | 375 | } |
| 334 | static inline struct ps3_system_bus_device *to_ps3_system_bus_device( | 376 | static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( |
| 335 | struct device *_dev) | 377 | struct device *_dev) |
| 336 | { | 378 | { |
| 337 | return container_of(_dev, struct ps3_system_bus_device, core); | 379 | return container_of(_dev, struct ps3_system_bus_device, core); |
| 338 | } | 380 | } |
| 381 | static inline struct ps3_system_bus_driver * | ||
| 382 | ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev) | ||
| 383 | { | ||
| 384 | BUG_ON(!_dev); | ||
| 385 | BUG_ON(!_dev->core.driver); | ||
| 386 | return ps3_drv_to_system_bus_drv(_dev->core.driver); | ||
| 387 | } | ||
| 339 | 388 | ||
| 340 | /** | 389 | /** |
| 341 | * ps3_system_bus_set_drvdata - | 390 | * ps3_system_bus_set_drvdata - |
| @@ -358,32 +407,17 @@ static inline void *ps3_system_bus_get_driver_data( | |||
| 358 | 407 | ||
| 359 | extern struct bus_type ps3_system_bus_type; | 408 | extern struct bus_type ps3_system_bus_type; |
| 360 | 409 | ||
| 361 | /* vuart routines */ | 410 | /* system manager */ |
| 362 | |||
| 363 | struct ps3_vuart_port_priv; | ||
| 364 | |||
| 365 | /** | ||
| 366 | * struct ps3_vuart_port_device - a device on a vuart port | ||
| 367 | */ | ||
| 368 | |||
| 369 | struct ps3_vuart_port_device { | ||
| 370 | enum ps3_match_id match_id; | ||
| 371 | struct device core; | ||
| 372 | struct ps3_vuart_port_priv* priv; /* private driver variables */ | ||
| 373 | 411 | ||
| 412 | struct ps3_sys_manager_ops { | ||
| 413 | struct ps3_system_bus_device *dev; | ||
| 414 | void (*power_off)(struct ps3_system_bus_device *dev); | ||
| 415 | void (*restart)(struct ps3_system_bus_device *dev); | ||
| 374 | }; | 416 | }; |
| 375 | 417 | ||
| 376 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev); | 418 | void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); |
| 377 | |||
| 378 | /* system manager */ | ||
| 379 | |||
| 380 | #ifdef CONFIG_PS3_SYS_MANAGER | ||
| 381 | void ps3_sys_manager_restart(void); | ||
| 382 | void ps3_sys_manager_power_off(void); | 419 | void ps3_sys_manager_power_off(void); |
| 383 | #else | 420 | void ps3_sys_manager_restart(void); |
| 384 | static inline void ps3_sys_manager_restart(void) {} | ||
| 385 | static inline void ps3_sys_manager_power_off(void) {} | ||
| 386 | #endif | ||
| 387 | 421 | ||
| 388 | struct ps3_prealloc { | 422 | struct ps3_prealloc { |
| 389 | const char *name; | 423 | const char *name; |
| @@ -393,5 +427,7 @@ struct ps3_prealloc { | |||
| 393 | }; | 427 | }; |
| 394 | 428 | ||
| 395 | extern struct ps3_prealloc ps3fb_videomemory; | 429 | extern struct ps3_prealloc ps3fb_videomemory; |
| 430 | extern struct ps3_prealloc ps3flash_bounce_buffer; | ||
| 431 | |||
| 396 | 432 | ||
| 397 | #endif | 433 | #endif |
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h index 9efc40f1c778..7df4250802de 100644 --- a/include/asm-powerpc/ps3av.h +++ b/include/asm-powerpc/ps3av.h | |||
| @@ -1,20 +1,23 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 2 | * PS3 AV backend support. |
| 3 | * Copyright 2006, 2007 Sony Corporation | ||
| 4 | * | 3 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
| 6 | * under the terms of the GNU General Public License as published | 5 | * Copyright 2007 Sony Corp. |
| 7 | * by the Free Software Foundation; version 2 of the License. | ||
| 8 | * | 6 | * |
| 9 | * This program is distributed in the hope that it will be useful, but | 7 | * This program is free software; you can redistribute it and/or modify |
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 8 | * it under the terms of the GNU General Public License as published by |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 9 | * the Free Software Foundation; version 2 of the License. |
| 12 | * General Public License for more details. | ||
| 13 | * | 10 | * |
| 14 | * You should have received a copy of the GNU General Public License along | 11 | * This program is distributed in the hope that it will be useful, |
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 17 | */ | 19 | */ |
| 20 | |||
| 18 | #ifndef _ASM_POWERPC_PS3AV_H_ | 21 | #ifndef _ASM_POWERPC_PS3AV_H_ |
| 19 | #define _ASM_POWERPC_PS3AV_H_ | 22 | #define _ASM_POWERPC_PS3AV_H_ |
| 20 | 23 | ||
| @@ -159,6 +162,9 @@ | |||
| 159 | #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000 | 162 | #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000 |
| 160 | /* video_out_format */ | 163 | /* video_out_format */ |
| 161 | #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000 | 164 | #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000 |
| 165 | /* video_cl_cnv */ | ||
| 166 | #define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT 0x0000 | ||
| 167 | #define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT 0x0010 | ||
| 162 | /* video_sync */ | 168 | /* video_sync */ |
| 163 | #define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001 | 169 | #define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001 |
| 164 | #define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004 | 170 | #define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004 |
| @@ -311,6 +317,8 @@ | |||
| 311 | #define PS3AV_MODE_MASK 0x000F | 317 | #define PS3AV_MODE_MASK 0x000F |
| 312 | #define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */ | 318 | #define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */ |
| 313 | #define PS3AV_MODE_DITHER 0x0800 | 319 | #define PS3AV_MODE_DITHER 0x0800 |
| 320 | #define PS3AV_MODE_COLOR 0x0400 | ||
| 321 | #define PS3AV_MODE_WHITE 0x0200 | ||
| 314 | #define PS3AV_MODE_FULL 0x0080 | 322 | #define PS3AV_MODE_FULL 0x0080 |
| 315 | #define PS3AV_MODE_DVI 0x0040 | 323 | #define PS3AV_MODE_DVI 0x0040 |
| 316 | #define PS3AV_MODE_RGB 0x0020 | 324 | #define PS3AV_MODE_RGB 0x0020 |
| @@ -529,9 +537,9 @@ struct ps3av_pkt_video_mode { | |||
| 529 | u32 video_out_format; /* in: out format */ | 537 | u32 video_out_format; /* in: out format */ |
| 530 | u32 video_format; /* in: input frame buffer format */ | 538 | u32 video_format; /* in: input frame buffer format */ |
| 531 | u8 reserved3; | 539 | u8 reserved3; |
| 532 | u8 reserved4; | 540 | u8 video_cl_cnv; /* in: color conversion */ |
| 533 | u16 video_order; /* in: input RGB order */ | 541 | u16 video_order; /* in: input RGB order */ |
| 534 | u32 reserved5; | 542 | u32 reserved4; |
| 535 | }; | 543 | }; |
| 536 | 544 | ||
| 537 | /* video: format */ | 545 | /* video: format */ |
| @@ -539,7 +547,8 @@ struct ps3av_pkt_video_format { | |||
| 539 | struct ps3av_send_hdr send_hdr; | 547 | struct ps3av_send_hdr send_hdr; |
| 540 | u32 video_head; /* in: head */ | 548 | u32 video_head; /* in: head */ |
| 541 | u32 video_format; /* in: frame buffer format */ | 549 | u32 video_format; /* in: frame buffer format */ |
| 542 | u16 reserved; | 550 | u8 reserved; |
| 551 | u8 video_cl_cnv; /* in: color conversion */ | ||
| 543 | u16 video_order; /* in: input RGB order */ | 552 | u16 video_order; /* in: input RGB order */ |
| 544 | }; | 553 | }; |
| 545 | 554 | ||
| @@ -698,12 +707,6 @@ static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_ | |||
| 698 | extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *, | 707 | extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *, |
| 699 | u32); | 708 | u32); |
| 700 | 709 | ||
| 701 | struct ps3_vuart_port_device; | ||
| 702 | extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev, | ||
| 703 | const void *buf, unsigned long size); | ||
| 704 | extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf, | ||
| 705 | unsigned long size, int timeout); | ||
| 706 | |||
| 707 | extern int ps3av_set_video_mode(u32, int); | 710 | extern int ps3av_set_video_mode(u32, int); |
| 708 | extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32); | 711 | extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32); |
| 709 | extern int ps3av_get_auto_mode(int); | 712 | extern int ps3av_get_auto_mode(int); |
| @@ -716,5 +719,8 @@ extern int ps3av_video_mute(int); | |||
| 716 | extern int ps3av_audio_mute(int); | 719 | extern int ps3av_audio_mute(int); |
| 717 | extern int ps3av_dev_open(void); | 720 | extern int ps3av_dev_open(void); |
| 718 | extern int ps3av_dev_close(void); | 721 | extern int ps3av_dev_close(void); |
| 722 | extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), | ||
| 723 | void *flip_data); | ||
| 724 | extern void ps3av_flip_ctl(int on); | ||
| 719 | 725 | ||
| 720 | #endif /* _ASM_POWERPC_PS3AV_H_ */ | 726 | #endif /* _ASM_POWERPC_PS3AV_H_ */ |
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h index ad81cf431964..3f121fe4010d 100644 --- a/include/asm-powerpc/ps3fb.h +++ b/include/asm-powerpc/ps3fb.h | |||
| @@ -41,16 +41,4 @@ struct ps3fb_ioctl_res { | |||
| 41 | __u32 num_frames; /* num of frame buffers */ | 41 | __u32 num_frames; /* num of frame buffers */ |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | #ifdef __KERNEL__ | ||
| 45 | |||
| 46 | #ifdef CONFIG_FB_PS3 | ||
| 47 | extern void ps3fb_flip_ctl(int on); | ||
| 48 | extern void ps3fb_cleanup(void); | ||
| 49 | #else | ||
| 50 | static inline void ps3fb_flip_ctl(int on) {} | ||
| 51 | static inline void ps3fb_cleanup(void) {} | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #endif /* __KERNEL__ */ | ||
| 55 | |||
| 56 | #endif /* _ASM_POWERPC_PS3FB_H_ */ | 44 | #endif /* _ASM_POWERPC_PS3FB_H_ */ |
diff --git a/include/asm-powerpc/ps3stor.h b/include/asm-powerpc/ps3stor.h new file mode 100644 index 000000000000..6fcaf714fa50 --- /dev/null +++ b/include/asm-powerpc/ps3stor.h | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | /* | ||
| 2 | * PS3 Storage Devices | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published | ||
| 9 | * by the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _ASM_POWERPC_PS3STOR_H_ | ||
| 22 | #define _ASM_POWERPC_PS3STOR_H_ | ||
| 23 | |||
| 24 | #include <linux/interrupt.h> | ||
| 25 | |||
| 26 | #include <asm/ps3.h> | ||
| 27 | |||
| 28 | |||
| 29 | struct ps3_storage_region { | ||
| 30 | unsigned int id; | ||
| 31 | u64 start; | ||
| 32 | u64 size; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct ps3_storage_device { | ||
| 36 | struct ps3_system_bus_device sbd; | ||
| 37 | |||
| 38 | struct ps3_dma_region dma_region; | ||
| 39 | unsigned int irq; | ||
| 40 | u64 blk_size; | ||
| 41 | |||
| 42 | u64 tag; | ||
| 43 | u64 lv1_status; | ||
| 44 | struct completion done; | ||
| 45 | |||
| 46 | unsigned long bounce_size; | ||
| 47 | void *bounce_buf; | ||
| 48 | u64 bounce_lpar; | ||
| 49 | dma_addr_t bounce_dma; | ||
| 50 | |||
| 51 | unsigned int num_regions; | ||
| 52 | unsigned long accessible_regions; | ||
| 53 | unsigned int region_idx; /* first accessible region */ | ||
| 54 | struct ps3_storage_region regions[0]; /* Must be last */ | ||
| 55 | }; | ||
| 56 | |||
| 57 | static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev) | ||
| 58 | { | ||
| 59 | return container_of(dev, struct ps3_storage_device, sbd.core); | ||
| 60 | } | ||
| 61 | |||
| 62 | extern int ps3stor_setup(struct ps3_storage_device *dev, | ||
| 63 | irq_handler_t handler); | ||
| 64 | extern void ps3stor_teardown(struct ps3_storage_device *dev); | ||
| 65 | extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, | ||
| 66 | u64 start_sector, u64 sectors, | ||
| 67 | int write); | ||
| 68 | extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, | ||
| 69 | u64 arg1, u64 arg2, u64 arg3, u64 arg4); | ||
| 70 | |||
| 71 | #endif /* _ASM_POWERPC_PS3STOR_H_ */ | ||
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h index 4ad77a13f865..13fccc5a4119 100644 --- a/include/asm-powerpc/ptrace.h +++ b/include/asm-powerpc/ptrace.h | |||
| @@ -92,6 +92,11 @@ extern unsigned long profile_pc(struct pt_regs *regs); | |||
| 92 | set_thread_flag(TIF_NOERROR); \ | 92 | set_thread_flag(TIF_NOERROR); \ |
| 93 | } while(0) | 93 | } while(0) |
| 94 | 94 | ||
| 95 | struct task_struct; | ||
| 96 | extern unsigned long ptrace_get_reg(struct task_struct *task, int regno); | ||
| 97 | extern int ptrace_put_reg(struct task_struct *task, int regno, | ||
| 98 | unsigned long data); | ||
| 99 | |||
| 95 | /* | 100 | /* |
| 96 | * We use the least-significant bit of the trap field to indicate | 101 | * We use the least-significant bit of the trap field to indicate |
| 97 | * whether we have saved the full set of registers, or only a | 102 | * whether we have saved the full set of registers, or only a |
| @@ -158,9 +163,7 @@ do { \ | |||
| 158 | 163 | ||
| 159 | #define PT_NIP 32 | 164 | #define PT_NIP 32 |
| 160 | #define PT_MSR 33 | 165 | #define PT_MSR 33 |
| 161 | #ifdef __KERNEL__ | ||
| 162 | #define PT_ORIG_R3 34 | 166 | #define PT_ORIG_R3 34 |
| 163 | #endif | ||
| 164 | #define PT_CTR 35 | 167 | #define PT_CTR 35 |
| 165 | #define PT_LNK 36 | 168 | #define PT_LNK 36 |
| 166 | #define PT_XER 37 | 169 | #define PT_XER 37 |
| @@ -169,11 +172,12 @@ do { \ | |||
| 169 | #define PT_MQ 39 | 172 | #define PT_MQ 39 |
| 170 | #else | 173 | #else |
| 171 | #define PT_SOFTE 39 | 174 | #define PT_SOFTE 39 |
| 175 | #endif | ||
| 172 | #define PT_TRAP 40 | 176 | #define PT_TRAP 40 |
| 173 | #define PT_DAR 41 | 177 | #define PT_DAR 41 |
| 174 | #define PT_DSISR 42 | 178 | #define PT_DSISR 42 |
| 175 | #define PT_RESULT 43 | 179 | #define PT_RESULT 43 |
| 176 | #endif | 180 | #define PT_REGS_COUNT 44 |
| 177 | 181 | ||
| 178 | #define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ | 182 | #define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ |
| 179 | 183 | ||
| @@ -229,7 +233,17 @@ do { \ | |||
| 229 | #define PTRACE_GET_DEBUGREG 25 | 233 | #define PTRACE_GET_DEBUGREG 25 |
| 230 | #define PTRACE_SET_DEBUGREG 26 | 234 | #define PTRACE_SET_DEBUGREG 26 |
| 231 | 235 | ||
| 232 | /* Additional PTRACE requests implemented on PowerPC. */ | 236 | /* (new) PTRACE requests using the same numbers as x86 and the same |
| 237 | * argument ordering. Additionally, they support more registers too | ||
| 238 | */ | ||
| 239 | #define PTRACE_GETREGS 12 | ||
| 240 | #define PTRACE_SETREGS 13 | ||
| 241 | #define PTRACE_GETFPREGS 14 | ||
| 242 | #define PTRACE_SETFPREGS 15 | ||
| 243 | #define PTRACE_GETREGS64 22 | ||
| 244 | #define PTRACE_SETREGS64 23 | ||
| 245 | |||
| 246 | /* (old) PTRACE requests with inverted arguments */ | ||
| 233 | #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ | 247 | #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ |
| 234 | #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ | 248 | #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ |
| 235 | #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ | 249 | #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ |
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 749c7f953b58..281011e953ec 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h | |||
| @@ -453,6 +453,8 @@ | |||
| 453 | #define SPRN_MMCRA 0x312 | 453 | #define SPRN_MMCRA 0x312 |
| 454 | #define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ | 454 | #define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ |
| 455 | #define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ | 455 | #define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ |
| 456 | #define MMCRA_SLOT 0x07000000UL /* SLOT bits (37-39) */ | ||
| 457 | #define MMCRA_SLOT_SHIFT 24 | ||
| 456 | #define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ | 458 | #define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ |
| 457 | #define POWER6_MMCRA_SIHV 0x0000040000000000ULL | 459 | #define POWER6_MMCRA_SIHV 0x0000040000000000ULL |
| 458 | #define POWER6_MMCRA_SIPR 0x0000020000000000ULL | 460 | #define POWER6_MMCRA_SIPR 0x0000020000000000ULL |
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 31d5054be20f..eedc828cef2d 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h | |||
| @@ -106,6 +106,14 @@ struct spu_context; | |||
| 106 | struct spu_runqueue; | 106 | struct spu_runqueue; |
| 107 | struct device_node; | 107 | struct device_node; |
| 108 | 108 | ||
| 109 | enum spu_utilization_state { | ||
| 110 | SPU_UTIL_SYSTEM, | ||
| 111 | SPU_UTIL_USER, | ||
| 112 | SPU_UTIL_IOWAIT, | ||
| 113 | SPU_UTIL_IDLE, | ||
| 114 | SPU_UTIL_MAX | ||
| 115 | }; | ||
| 116 | |||
| 109 | struct spu { | 117 | struct spu { |
| 110 | const char *name; | 118 | const char *name; |
| 111 | unsigned long local_store_phys; | 119 | unsigned long local_store_phys; |
| @@ -156,6 +164,21 @@ struct spu { | |||
| 156 | u64 shadow_int_mask_RW[3]; | 164 | u64 shadow_int_mask_RW[3]; |
| 157 | 165 | ||
| 158 | struct sys_device sysdev; | 166 | struct sys_device sysdev; |
| 167 | |||
| 168 | struct { | ||
| 169 | /* protected by interrupt reentrancy */ | ||
| 170 | enum spu_utilization_state utilization_state; | ||
| 171 | unsigned long tstamp; /* time of last ctx switch */ | ||
| 172 | unsigned long times[SPU_UTIL_MAX]; | ||
| 173 | unsigned long long vol_ctx_switch; | ||
| 174 | unsigned long long invol_ctx_switch; | ||
| 175 | unsigned long long min_flt; | ||
| 176 | unsigned long long maj_flt; | ||
| 177 | unsigned long long hash_flt; | ||
| 178 | unsigned long long slb_flt; | ||
| 179 | unsigned long long class2_intr; | ||
| 180 | unsigned long long libassist; | ||
| 181 | } stats; | ||
| 159 | }; | 182 | }; |
| 160 | 183 | ||
| 161 | struct spu *spu_alloc(void); | 184 | struct spu *spu_alloc(void); |
| @@ -448,6 +471,7 @@ struct spu_priv1 { | |||
| 448 | #define MFC_STATE1_PROBLEM_STATE_MASK 0x08ull | 471 | #define MFC_STATE1_PROBLEM_STATE_MASK 0x08ull |
| 449 | #define MFC_STATE1_RELOCATE_MASK 0x10ull | 472 | #define MFC_STATE1_RELOCATE_MASK 0x10ull |
| 450 | #define MFC_STATE1_MASTER_RUN_CONTROL_MASK 0x20ull | 473 | #define MFC_STATE1_MASTER_RUN_CONTROL_MASK 0x20ull |
| 474 | #define MFC_STATE1_TABLE_SEARCH_MASK 0x40ull | ||
| 451 | u64 mfc_lpid_RW; /* 0x008 */ | 475 | u64 mfc_lpid_RW; /* 0x008 */ |
| 452 | u64 spu_idr_RW; /* 0x010 */ | 476 | u64 spu_idr_RW; /* 0x010 */ |
| 453 | u64 mfc_vr_RO; /* 0x018 */ | 477 | u64 mfc_vr_RO; /* 0x018 */ |
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h index c2fe79d4f90f..b3ca41fc8bb1 100644 --- a/include/asm-powerpc/syscalls.h +++ b/include/asm-powerpc/syscalls.h | |||
| @@ -43,16 +43,9 @@ asmlinkage long ppc_newuname(struct new_utsname __user * name); | |||
| 43 | 43 | ||
| 44 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, | 44 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, |
| 45 | size_t sigsetsize); | 45 | size_t sigsetsize); |
| 46 | |||
| 47 | #ifndef __powerpc64__ | ||
| 48 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, | ||
| 49 | stack_t __user *uoss, int r5, int r6, int r7, int r8, | ||
| 50 | struct pt_regs *regs); | ||
| 51 | #else /* __powerpc64__ */ | ||
| 52 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, | 46 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, |
| 53 | stack_t __user *uoss, unsigned long r5, unsigned long r6, | 47 | stack_t __user *uoss, unsigned long r5, unsigned long r6, |
| 54 | unsigned long r7, unsigned long r8, struct pt_regs *regs); | 48 | unsigned long r7, unsigned long r8, struct pt_regs *regs); |
| 55 | #endif /* __powerpc64__ */ | ||
| 56 | 49 | ||
| 57 | #endif /* __KERNEL__ */ | 50 | #endif /* __KERNEL__ */ |
| 58 | #endif /* __ASM_POWERPC_SYSCALLS_H */ | 51 | #endif /* __ASM_POWERPC_SYSCALLS_H */ |
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 09621f611dbc..32aa42b748be 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
| @@ -43,7 +43,7 @@ | |||
| 43 | #ifdef CONFIG_SMP | 43 | #ifdef CONFIG_SMP |
| 44 | #define smp_mb() mb() | 44 | #define smp_mb() mb() |
| 45 | #define smp_rmb() rmb() | 45 | #define smp_rmb() rmb() |
| 46 | #define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory") | 46 | #define smp_wmb() eieio() |
| 47 | #define smp_read_barrier_depends() read_barrier_depends() | 47 | #define smp_read_barrier_depends() read_barrier_depends() |
| 48 | #else | 48 | #else |
| 49 | #define smp_mb() barrier() | 49 | #define smp_mb() barrier() |
| @@ -559,5 +559,7 @@ static inline void create_function_call(unsigned long addr, void * func) | |||
| 559 | extern void account_system_vtime(struct task_struct *); | 559 | extern void account_system_vtime(struct task_struct *); |
| 560 | #endif | 560 | #endif |
| 561 | 561 | ||
| 562 | extern struct dentry *powerpc_debugfs_root; | ||
| 563 | |||
| 562 | #endif /* __KERNEL__ */ | 564 | #endif /* __KERNEL__ */ |
| 563 | #endif /* _ASM_POWERPC_SYSTEM_H */ | 565 | #endif /* _ASM_POWERPC_SYSTEM_H */ |
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h index 5e79198f7d18..6698188ca550 100644 --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h | |||
| @@ -152,6 +152,10 @@ struct ktermios { | |||
| 152 | #define B3000000 00034 | 152 | #define B3000000 00034 |
| 153 | #define B3500000 00035 | 153 | #define B3500000 00035 |
| 154 | #define B4000000 00036 | 154 | #define B4000000 00036 |
| 155 | #define BOTHER 00037 | ||
| 156 | |||
| 157 | #define CIBAUD 077600000 | ||
| 158 | #define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ | ||
| 155 | 159 | ||
| 156 | #define CSIZE 00001400 | 160 | #define CSIZE 00001400 |
| 157 | #define CS5 00000000 | 161 | #define CS5 00000000 |
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index 3f32ca8bfec9..9d9aeca8ad22 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h | |||
| @@ -113,8 +113,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 113 | #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling | 113 | #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling |
| 114 | TIF_NEED_RESCHED */ | 114 | TIF_NEED_RESCHED */ |
| 115 | #define TIF_32BIT 5 /* 32 bit binary */ | 115 | #define TIF_32BIT 5 /* 32 bit binary */ |
| 116 | #define TIF_RUNLATCH 6 /* Is the runlatch enabled? */ | 116 | #define TIF_PERFMON_WORK 6 /* work for pfm_handle_work() */ |
| 117 | #define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */ | 117 | #define TIF_PERFMON_CTXSW 7 /* perfmon needs ctxsw calls */ |
| 118 | #define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */ | 118 | #define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */ |
| 119 | #define TIF_SINGLESTEP 9 /* singlestepping active */ | 119 | #define TIF_SINGLESTEP 9 /* singlestepping active */ |
| 120 | #define TIF_MEMDIE 10 | 120 | #define TIF_MEMDIE 10 |
| @@ -123,6 +123,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 123 | #define TIF_NOERROR 14 /* Force successful syscall return */ | 123 | #define TIF_NOERROR 14 /* Force successful syscall return */ |
| 124 | #define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */ | 124 | #define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */ |
| 125 | #define TIF_FREEZE 16 /* Freezing for suspend */ | 125 | #define TIF_FREEZE 16 /* Freezing for suspend */ |
| 126 | #define TIF_RUNLATCH 17 /* Is the runlatch enabled? */ | ||
| 127 | #define TIF_ABI_PENDING 18 /* 32/64 bit switch needed */ | ||
| 126 | 128 | ||
| 127 | /* as above, but as bit values */ | 129 | /* as above, but as bit values */ |
| 128 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 130 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
| @@ -131,8 +133,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 131 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | 133 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) |
| 132 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 134 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
| 133 | #define _TIF_32BIT (1<<TIF_32BIT) | 135 | #define _TIF_32BIT (1<<TIF_32BIT) |
| 134 | #define _TIF_RUNLATCH (1<<TIF_RUNLATCH) | 136 | #define _TIF_PERFMON_WORK (1<<TIF_PERFMON_WORK) |
| 135 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) | 137 | #define _TIF_PERFMON_CTXSW (1<<TIF_PERFMON_CTXSW) |
| 136 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 138 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
| 137 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) | 139 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) |
| 138 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 140 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
| @@ -140,6 +142,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 140 | #define _TIF_NOERROR (1<<TIF_NOERROR) | 142 | #define _TIF_NOERROR (1<<TIF_NOERROR) |
| 141 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) | 143 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) |
| 142 | #define _TIF_FREEZE (1<<TIF_FREEZE) | 144 | #define _TIF_FREEZE (1<<TIF_FREEZE) |
| 145 | #define _TIF_RUNLATCH (1<<TIF_RUNLATCH) | ||
| 146 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) | ||
| 143 | #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) | 147 | #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) |
| 144 | 148 | ||
| 145 | #define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ | 149 | #define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ |
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index 3fd57c048f59..d7f5ddfbaac7 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h | |||
| @@ -232,7 +232,7 @@ extern void account_process_vtime(struct task_struct *tsk); | |||
| 232 | #define account_process_vtime(tsk) do { } while (0) | 232 | #define account_process_vtime(tsk) do { } while (0) |
| 233 | #endif | 233 | #endif |
| 234 | 234 | ||
| 235 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR) | 235 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) |
| 236 | extern void calculate_steal_time(void); | 236 | extern void calculate_steal_time(void); |
| 237 | extern void snapshot_timebases(void); | 237 | extern void snapshot_timebases(void); |
| 238 | #else | 238 | #else |
| @@ -240,5 +240,7 @@ extern void snapshot_timebases(void); | |||
| 240 | #define snapshot_timebases() do { } while (0) | 240 | #define snapshot_timebases() do { } while (0) |
| 241 | #endif | 241 | #endif |
| 242 | 242 | ||
| 243 | extern void iSeries_time_init_early(void); | ||
| 244 | |||
| 243 | #endif /* __KERNEL__ */ | 245 | #endif /* __KERNEL__ */ |
| 244 | #endif /* __POWERPC_TIME_H */ | 246 | #endif /* __POWERPC_TIME_H */ |
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index 86e6266a028b..99a0439baa50 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h | |||
| @@ -155,6 +155,11 @@ static inline void flush_tlb_kernel_range(unsigned long start, | |||
| 155 | { | 155 | { |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | /* Private function for use by PCI IO mapping code */ | ||
| 159 | extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | ||
| 160 | unsigned long end); | ||
| 161 | |||
| 162 | |||
| 158 | #endif | 163 | #endif |
| 159 | 164 | ||
| 160 | /* | 165 | /* |
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 73710d617775..12e631f0fb77 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h | |||
| @@ -120,5 +120,10 @@ struct fsl_spi_platform_data { | |||
| 120 | u32 sysclk; | 120 | u32 sysclk; |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | struct mpc8xx_pcmcia_ops { | ||
| 124 | void(*hw_ctrl)(int slot, int enable); | ||
| 125 | int(*voltage_set)(int slot, int vcc, int vpp); | ||
| 126 | }; | ||
| 127 | |||
| 123 | #endif /* _FSL_DEVICE_H_ */ | 128 | #endif /* _FSL_DEVICE_H_ */ |
| 124 | #endif /* __KERNEL__ */ | 129 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 4b7ee83787c1..132b260aef1e 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h | |||
| @@ -65,9 +65,10 @@ extern struct vm_struct *get_vm_area_node(unsigned long size, | |||
| 65 | unsigned long flags, int node, | 65 | unsigned long flags, int node, |
| 66 | gfp_t gfp_mask); | 66 | gfp_t gfp_mask); |
| 67 | extern struct vm_struct *remove_vm_area(void *addr); | 67 | extern struct vm_struct *remove_vm_area(void *addr); |
| 68 | |||
| 68 | extern int map_vm_area(struct vm_struct *area, pgprot_t prot, | 69 | extern int map_vm_area(struct vm_struct *area, pgprot_t prot, |
| 69 | struct page ***pages); | 70 | struct page ***pages); |
| 70 | extern void unmap_vm_area(struct vm_struct *area); | 71 | extern void unmap_kernel_range(unsigned long addr, unsigned long size); |
| 71 | 72 | ||
| 72 | /* | 73 | /* |
| 73 | * Internals. Dont't use.. | 74 | * Internals. Dont't use.. |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index d3a9c5368257..ddf87145cc49 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
| @@ -68,12 +68,12 @@ static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr, | |||
| 68 | } while (pud++, addr = next, addr != end); | 68 | } while (pud++, addr = next, addr != end); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void unmap_vm_area(struct vm_struct *area) | 71 | void unmap_kernel_range(unsigned long addr, unsigned long size) |
| 72 | { | 72 | { |
| 73 | pgd_t *pgd; | 73 | pgd_t *pgd; |
| 74 | unsigned long next; | 74 | unsigned long next; |
| 75 | unsigned long addr = (unsigned long) area->addr; | 75 | unsigned long start = addr; |
| 76 | unsigned long end = addr + area->size; | 76 | unsigned long end = addr + size; |
| 77 | 77 | ||
| 78 | BUG_ON(addr >= end); | 78 | BUG_ON(addr >= end); |
| 79 | pgd = pgd_offset_k(addr); | 79 | pgd = pgd_offset_k(addr); |
| @@ -84,7 +84,12 @@ void unmap_vm_area(struct vm_struct *area) | |||
| 84 | continue; | 84 | continue; |
| 85 | vunmap_pud_range(pgd, addr, next); | 85 | vunmap_pud_range(pgd, addr, next); |
| 86 | } while (pgd++, addr = next, addr != end); | 86 | } while (pgd++, addr = next, addr != end); |
| 87 | flush_tlb_kernel_range((unsigned long) area->addr, end); | 87 | flush_tlb_kernel_range(start, end); |
| 88 | } | ||
| 89 | |||
| 90 | static void unmap_vm_area(struct vm_struct *area) | ||
| 91 | { | ||
| 92 | unmap_kernel_range((unsigned long)area->addr, area->size); | ||
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | static int vmap_pte_range(pmd_t *pmd, unsigned long addr, | 95 | static int vmap_pte_range(pmd_t *pmd, unsigned long addr, |
