diff options
Diffstat (limited to 'arch/ppc')
| -rw-r--r-- | arch/ppc/Kconfig | 4 | ||||
| -rw-r--r-- | arch/ppc/Makefile | 1 | ||||
| -rw-r--r-- | arch/ppc/boot/images/Makefile | 3 | ||||
| -rw-r--r-- | arch/ppc/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/ppc/kernel/align.c | 12 | ||||
| -rw-r--r-- | arch/ppc/kernel/cpu_setup_6xx.S | 42 | ||||
| -rw-r--r-- | arch/ppc/kernel/entry.S | 59 | ||||
| -rw-r--r-- | arch/ppc/kernel/fpu.S | 133 | ||||
| -rw-r--r-- | arch/ppc/kernel/head.S | 163 | ||||
| -rw-r--r-- | arch/ppc/kernel/head_44x.S | 6 | ||||
| -rw-r--r-- | arch/ppc/kernel/head_booke.h | 7 | ||||
| -rw-r--r-- | arch/ppc/kernel/head_fsl_booke.S | 8 | ||||
| -rw-r--r-- | arch/ppc/kernel/misc.S | 12 | ||||
| -rw-r--r-- | arch/ppc/kernel/ptrace.c | 5 | ||||
| -rw-r--r-- | arch/ppc/kernel/traps.c | 2 | ||||
| -rw-r--r-- | arch/ppc/platforms/pmac_cache.S | 54 | ||||
| -rw-r--r-- | arch/ppc/platforms/pmac_feature.c | 216 | ||||
| -rw-r--r-- | arch/ppc/platforms/pmac_sleep.S | 4 | ||||
| -rw-r--r-- | arch/ppc/platforms/radstone_ppc7d.c | 60 | ||||
| -rw-r--r-- | arch/ppc/platforms/radstone_ppc7d.h | 1 | ||||
| -rw-r--r-- | arch/ppc/syslib/cpm2_pic.c | 5 |
21 files changed, 492 insertions, 306 deletions
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 74aa1e92a395..c3d941345e3d 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig | |||
| @@ -53,6 +53,7 @@ choice | |||
| 53 | 53 | ||
| 54 | config 6xx | 54 | config 6xx |
| 55 | bool "6xx/7xx/74xx/52xx/82xx/83xx" | 55 | bool "6xx/7xx/74xx/52xx/82xx/83xx" |
| 56 | select PPC_FPU | ||
| 56 | help | 57 | help |
| 57 | There are four types of PowerPC chips supported. The more common | 58 | There are four types of PowerPC chips supported. The more common |
| 58 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded | 59 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded |
| @@ -86,6 +87,9 @@ config E500 | |||
| 86 | 87 | ||
| 87 | endchoice | 88 | endchoice |
| 88 | 89 | ||
| 90 | config PPC_FPU | ||
| 91 | bool | ||
| 92 | |||
| 89 | config BOOKE | 93 | config BOOKE |
| 90 | bool | 94 | bool |
| 91 | depends on E500 | 95 | depends on E500 |
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 73cbdda5b597..0432a25b4735 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile | |||
| @@ -53,6 +53,7 @@ head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o | |||
| 53 | 53 | ||
| 54 | head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o | 54 | head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o |
| 55 | head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o | 55 | head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o |
| 56 | head-$(CONFIG_PPC_FPU) += arch/ppc/kernel/fpu.o | ||
| 56 | 57 | ||
| 57 | core-y += arch/ppc/kernel/ arch/ppc/platforms/ \ | 58 | core-y += arch/ppc/kernel/ arch/ppc/platforms/ \ |
| 58 | arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/ | 59 | arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/ |
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile index 774de8e23871..f850fb0fb511 100644 --- a/arch/ppc/boot/images/Makefile +++ b/arch/ppc/boot/images/Makefile | |||
| @@ -20,8 +20,9 @@ quiet_cmd_uimage = UIMAGE $@ | |||
| 20 | 20 | ||
| 21 | targets += uImage | 21 | targets += uImage |
| 22 | $(obj)/uImage: $(obj)/vmlinux.gz | 22 | $(obj)/uImage: $(obj)/vmlinux.gz |
| 23 | $(Q)rm -f $@ | ||
| 23 | $(call if_changed,uimage) | 24 | $(call if_changed,uimage) |
| 24 | @echo ' Image $@ is ready' | 25 | @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made') |
| 25 | 26 | ||
| 26 | # Files generated that shall be removed upon make clean | 27 | # Files generated that shall be removed upon make clean |
| 27 | clean-files := sImage vmapus vmlinux* miboot* zImage* uImage | 28 | clean-files := sImage vmapus vmlinux* miboot* zImage* uImage |
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 86bc878cb3ee..b284451802c9 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile | |||
| @@ -9,6 +9,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | |||
| 9 | extra-$(CONFIG_8xx) := head_8xx.o | 9 | extra-$(CONFIG_8xx) := head_8xx.o |
| 10 | extra-$(CONFIG_6xx) += idle_6xx.o | 10 | extra-$(CONFIG_6xx) += idle_6xx.o |
| 11 | extra-$(CONFIG_POWER4) += idle_power4.o | 11 | extra-$(CONFIG_POWER4) += idle_power4.o |
| 12 | extra-$(CONFIG_PPC_FPU) += fpu.o | ||
| 12 | extra-y += vmlinux.lds | 13 | extra-y += vmlinux.lds |
| 13 | 14 | ||
| 14 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ | 15 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ |
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c index 79c929475037..ff81da9598d8 100644 --- a/arch/ppc/kernel/align.c +++ b/arch/ppc/kernel/align.c | |||
| @@ -290,6 +290,10 @@ fix_alignment(struct pt_regs *regs) | |||
| 290 | /* lwm, stmw */ | 290 | /* lwm, stmw */ |
| 291 | nb = (32 - reg) * 4; | 291 | nb = (32 - reg) * 4; |
| 292 | } | 292 | } |
| 293 | |||
| 294 | if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0)) | ||
| 295 | return -EFAULT; /* bad address */ | ||
| 296 | |||
| 293 | rptr = (unsigned char *) ®s->gpr[reg]; | 297 | rptr = (unsigned char *) ®s->gpr[reg]; |
| 294 | if (flags & LD) { | 298 | if (flags & LD) { |
| 295 | for (i = 0; i < nb; ++i) | 299 | for (i = 0; i < nb; ++i) |
| @@ -368,16 +372,24 @@ fix_alignment(struct pt_regs *regs) | |||
| 368 | 372 | ||
| 369 | /* Single-precision FP load and store require conversions... */ | 373 | /* Single-precision FP load and store require conversions... */ |
| 370 | case LD+F+S: | 374 | case LD+F+S: |
| 375 | #ifdef CONFIG_PPC_FPU | ||
| 371 | preempt_disable(); | 376 | preempt_disable(); |
| 372 | enable_kernel_fp(); | 377 | enable_kernel_fp(); |
| 373 | cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); | 378 | cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); |
| 374 | preempt_enable(); | 379 | preempt_enable(); |
| 380 | #else | ||
| 381 | return 0; | ||
| 382 | #endif | ||
| 375 | break; | 383 | break; |
| 376 | case ST+F+S: | 384 | case ST+F+S: |
| 385 | #ifdef CONFIG_PPC_FPU | ||
| 377 | preempt_disable(); | 386 | preempt_disable(); |
| 378 | enable_kernel_fp(); | 387 | enable_kernel_fp(); |
| 379 | cvt_df(&data.d, &data.f, ¤t->thread.fpscr); | 388 | cvt_df(&data.d, &data.f, ¤t->thread.fpscr); |
| 380 | preempt_enable(); | 389 | preempt_enable(); |
| 390 | #else | ||
| 391 | return 0; | ||
| 392 | #endif | ||
| 381 | break; | 393 | break; |
| 382 | } | 394 | } |
| 383 | 395 | ||
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index 74f781b486a3..468721d9ebd2 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S | |||
| @@ -30,12 +30,14 @@ _GLOBAL(__setup_cpu_604) | |||
| 30 | blr | 30 | blr |
| 31 | _GLOBAL(__setup_cpu_750) | 31 | _GLOBAL(__setup_cpu_750) |
| 32 | mflr r4 | 32 | mflr r4 |
| 33 | bl __init_fpu_registers | ||
| 33 | bl setup_common_caches | 34 | bl setup_common_caches |
| 34 | bl setup_750_7400_hid0 | 35 | bl setup_750_7400_hid0 |
| 35 | mtlr r4 | 36 | mtlr r4 |
| 36 | blr | 37 | blr |
| 37 | _GLOBAL(__setup_cpu_750cx) | 38 | _GLOBAL(__setup_cpu_750cx) |
| 38 | mflr r4 | 39 | mflr r4 |
| 40 | bl __init_fpu_registers | ||
| 39 | bl setup_common_caches | 41 | bl setup_common_caches |
| 40 | bl setup_750_7400_hid0 | 42 | bl setup_750_7400_hid0 |
| 41 | bl setup_750cx | 43 | bl setup_750cx |
| @@ -43,6 +45,7 @@ _GLOBAL(__setup_cpu_750cx) | |||
| 43 | blr | 45 | blr |
| 44 | _GLOBAL(__setup_cpu_750fx) | 46 | _GLOBAL(__setup_cpu_750fx) |
| 45 | mflr r4 | 47 | mflr r4 |
| 48 | bl __init_fpu_registers | ||
| 46 | bl setup_common_caches | 49 | bl setup_common_caches |
| 47 | bl setup_750_7400_hid0 | 50 | bl setup_750_7400_hid0 |
| 48 | bl setup_750fx | 51 | bl setup_750fx |
| @@ -50,6 +53,7 @@ _GLOBAL(__setup_cpu_750fx) | |||
| 50 | blr | 53 | blr |
| 51 | _GLOBAL(__setup_cpu_7400) | 54 | _GLOBAL(__setup_cpu_7400) |
| 52 | mflr r4 | 55 | mflr r4 |
| 56 | bl __init_fpu_registers | ||
| 53 | bl setup_7400_workarounds | 57 | bl setup_7400_workarounds |
| 54 | bl setup_common_caches | 58 | bl setup_common_caches |
| 55 | bl setup_750_7400_hid0 | 59 | bl setup_750_7400_hid0 |
| @@ -57,6 +61,7 @@ _GLOBAL(__setup_cpu_7400) | |||
| 57 | blr | 61 | blr |
| 58 | _GLOBAL(__setup_cpu_7410) | 62 | _GLOBAL(__setup_cpu_7410) |
| 59 | mflr r4 | 63 | mflr r4 |
| 64 | bl __init_fpu_registers | ||
| 60 | bl setup_7410_workarounds | 65 | bl setup_7410_workarounds |
| 61 | bl setup_common_caches | 66 | bl setup_common_caches |
| 62 | bl setup_750_7400_hid0 | 67 | bl setup_750_7400_hid0 |
| @@ -80,7 +85,7 @@ setup_common_caches: | |||
| 80 | bne 1f /* don't invalidate the D-cache */ | 85 | bne 1f /* don't invalidate the D-cache */ |
| 81 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ | 86 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ |
| 82 | 1: sync | 87 | 1: sync |
| 83 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ | 88 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ |
| 84 | sync | 89 | sync |
| 85 | mtspr SPRN_HID0,r11 /* enable caches */ | 90 | mtspr SPRN_HID0,r11 /* enable caches */ |
| 86 | sync | 91 | sync |
| @@ -152,9 +157,13 @@ setup_7410_workarounds: | |||
| 152 | setup_750_7400_hid0: | 157 | setup_750_7400_hid0: |
| 153 | mfspr r11,SPRN_HID0 | 158 | mfspr r11,SPRN_HID0 |
| 154 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC | 159 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC |
| 160 | oris r11,r11,HID0_DPM@h | ||
| 155 | BEGIN_FTR_SECTION | 161 | BEGIN_FTR_SECTION |
| 156 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 162 | xori r11,r11,HID0_BTIC |
| 157 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 163 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
| 164 | BEGIN_FTR_SECTION | ||
| 165 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ | ||
| 166 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) | ||
| 158 | li r3,HID0_SPD | 167 | li r3,HID0_SPD |
| 159 | andc r11,r11,r3 /* clear SPD: enable speculative */ | 168 | andc r11,r11,r3 /* clear SPD: enable speculative */ |
| 160 | li r3,0 | 169 | li r3,0 |
| @@ -218,13 +227,15 @@ setup_745x_specifics: | |||
| 218 | 227 | ||
| 219 | /* All of the bits we have to set..... | 228 | /* All of the bits we have to set..... |
| 220 | */ | 229 | */ |
| 221 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC | 230 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE |
| 231 | ori r11,r11,HID0_LRSTK | HID0_BTIC | ||
| 232 | oris r11,r11,HID0_DPM@h | ||
| 222 | BEGIN_FTR_SECTION | 233 | BEGIN_FTR_SECTION |
| 223 | xori r11,r11,HID0_BTIC | 234 | xori r11,r11,HID0_BTIC |
| 224 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | 235 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
| 225 | BEGIN_FTR_SECTION | 236 | BEGIN_FTR_SECTION |
| 226 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 237 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ |
| 227 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 238 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) |
| 228 | 239 | ||
| 229 | /* All of the bits we have to clear.... | 240 | /* All of the bits we have to clear.... |
| 230 | */ | 241 | */ |
| @@ -248,6 +259,25 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | |||
| 248 | isync | 259 | isync |
| 249 | blr | 260 | blr |
| 250 | 261 | ||
| 262 | /* | ||
| 263 | * Initialize the FPU registers. This is needed to work around an errata | ||
| 264 | * in some 750 cpus where using a not yet initialized FPU register after | ||
| 265 | * power on reset may hang the CPU | ||
| 266 | */ | ||
| 267 | _GLOBAL(__init_fpu_registers) | ||
| 268 | mfmsr r10 | ||
| 269 | ori r11,r10,MSR_FP | ||
| 270 | mtmsr r11 | ||
| 271 | isync | ||
| 272 | addis r9,r3,empty_zero_page@ha | ||
| 273 | addi r9,r9,empty_zero_page@l | ||
| 274 | REST_32FPRS(0,r9) | ||
| 275 | sync | ||
| 276 | mtmsr r10 | ||
| 277 | isync | ||
| 278 | blr | ||
| 279 | |||
| 280 | |||
| 251 | /* Definitions for the table use to save CPU states */ | 281 | /* Definitions for the table use to save CPU states */ |
| 252 | #define CS_HID0 0 | 282 | #define CS_HID0 0 |
| 253 | #define CS_HID1 4 | 283 | #define CS_HID1 4 |
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 035217d6c0f1..5f075dbc4ee7 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S | |||
| @@ -563,6 +563,65 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 563 | addi r1,r1,INT_FRAME_SIZE | 563 | addi r1,r1,INT_FRAME_SIZE |
| 564 | blr | 564 | blr |
| 565 | 565 | ||
| 566 | .globl fast_exception_return | ||
| 567 | fast_exception_return: | ||
| 568 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
| 569 | andi. r10,r9,MSR_RI /* check for recoverable interrupt */ | ||
| 570 | beq 1f /* if not, we've got problems */ | ||
| 571 | #endif | ||
| 572 | |||
| 573 | 2: REST_4GPRS(3, r11) | ||
| 574 | lwz r10,_CCR(r11) | ||
| 575 | REST_GPR(1, r11) | ||
| 576 | mtcr r10 | ||
| 577 | lwz r10,_LINK(r11) | ||
| 578 | mtlr r10 | ||
| 579 | REST_GPR(10, r11) | ||
| 580 | mtspr SPRN_SRR1,r9 | ||
| 581 | mtspr SPRN_SRR0,r12 | ||
| 582 | REST_GPR(9, r11) | ||
| 583 | REST_GPR(12, r11) | ||
| 584 | lwz r11,GPR11(r11) | ||
| 585 | SYNC | ||
| 586 | RFI | ||
| 587 | |||
| 588 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
| 589 | /* check if the exception happened in a restartable section */ | ||
| 590 | 1: lis r3,exc_exit_restart_end@ha | ||
| 591 | addi r3,r3,exc_exit_restart_end@l | ||
| 592 | cmplw r12,r3 | ||
| 593 | bge 3f | ||
| 594 | lis r4,exc_exit_restart@ha | ||
| 595 | addi r4,r4,exc_exit_restart@l | ||
| 596 | cmplw r12,r4 | ||
| 597 | blt 3f | ||
| 598 | lis r3,fee_restarts@ha | ||
| 599 | tophys(r3,r3) | ||
| 600 | lwz r5,fee_restarts@l(r3) | ||
| 601 | addi r5,r5,1 | ||
| 602 | stw r5,fee_restarts@l(r3) | ||
| 603 | mr r12,r4 /* restart at exc_exit_restart */ | ||
| 604 | b 2b | ||
| 605 | |||
| 606 | .comm fee_restarts,4 | ||
| 607 | |||
| 608 | /* aargh, a nonrecoverable interrupt, panic */ | ||
| 609 | /* aargh, we don't know which trap this is */ | ||
| 610 | /* but the 601 doesn't implement the RI bit, so assume it's OK */ | ||
| 611 | 3: | ||
| 612 | BEGIN_FTR_SECTION | ||
| 613 | b 2b | ||
| 614 | END_FTR_SECTION_IFSET(CPU_FTR_601) | ||
| 615 | li r10,-1 | ||
| 616 | stw r10,TRAP(r11) | ||
| 617 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 618 | lis r10,MSR_KERNEL@h | ||
| 619 | ori r10,r10,MSR_KERNEL@l | ||
| 620 | bl transfer_to_handler_full | ||
| 621 | .long nonrecoverable_exception | ||
| 622 | .long ret_from_except | ||
| 623 | #endif | ||
| 624 | |||
| 566 | .globl sigreturn_exit | 625 | .globl sigreturn_exit |
| 567 | sigreturn_exit: | 626 | sigreturn_exit: |
| 568 | subi r1,r3,STACK_FRAME_OVERHEAD | 627 | subi r1,r3,STACK_FRAME_OVERHEAD |
diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S new file mode 100644 index 000000000000..6189b26f640f --- /dev/null +++ b/arch/ppc/kernel/fpu.S | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* | ||
| 2 | * FPU support code, moved here from head.S so that it can be used | ||
| 3 | * by chips which use other head-whatever.S files. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License | ||
| 7 | * as published by the Free Software Foundation; either version | ||
| 8 | * 2 of the License, or (at your option) any later version. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/config.h> | ||
| 13 | #include <asm/processor.h> | ||
| 14 | #include <asm/page.h> | ||
| 15 | #include <asm/mmu.h> | ||
| 16 | #include <asm/pgtable.h> | ||
| 17 | #include <asm/cputable.h> | ||
| 18 | #include <asm/cache.h> | ||
| 19 | #include <asm/thread_info.h> | ||
| 20 | #include <asm/ppc_asm.h> | ||
| 21 | #include <asm/offsets.h> | ||
| 22 | |||
| 23 | /* | ||
| 24 | * This task wants to use the FPU now. | ||
| 25 | * On UP, disable FP for the task which had the FPU previously, | ||
| 26 | * and save its floating-point registers in its thread_struct. | ||
| 27 | * Load up this task's FP registers from its thread_struct, | ||
| 28 | * enable the FPU for the current task and return to the task. | ||
| 29 | */ | ||
| 30 | .globl load_up_fpu | ||
| 31 | load_up_fpu: | ||
| 32 | mfmsr r5 | ||
| 33 | ori r5,r5,MSR_FP | ||
| 34 | #ifdef CONFIG_PPC64BRIDGE | ||
| 35 | clrldi r5,r5,1 /* turn off 64-bit mode */ | ||
| 36 | #endif /* CONFIG_PPC64BRIDGE */ | ||
| 37 | SYNC | ||
| 38 | MTMSRD(r5) /* enable use of fpu now */ | ||
| 39 | isync | ||
| 40 | /* | ||
| 41 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
| 42 | * horrendously complex, especially when a task switches from one CPU | ||
| 43 | * to another. Instead we call giveup_fpu in switch_to. | ||
| 44 | */ | ||
| 45 | #ifndef CONFIG_SMP | ||
| 46 | tophys(r6,0) /* get __pa constant */ | ||
| 47 | addis r3,r6,last_task_used_math@ha | ||
| 48 | lwz r4,last_task_used_math@l(r3) | ||
| 49 | cmpwi 0,r4,0 | ||
| 50 | beq 1f | ||
| 51 | add r4,r4,r6 | ||
| 52 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | ||
| 53 | SAVE_32FPRS(0, r4) | ||
| 54 | mffs fr0 | ||
| 55 | stfd fr0,THREAD_FPSCR-4(r4) | ||
| 56 | lwz r5,PT_REGS(r4) | ||
| 57 | add r5,r5,r6 | ||
| 58 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 59 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | ||
| 60 | andc r4,r4,r10 /* disable FP for previous task */ | ||
| 61 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 62 | 1: | ||
| 63 | #endif /* CONFIG_SMP */ | ||
| 64 | /* enable use of FP after return */ | ||
| 65 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | ||
| 66 | lwz r4,THREAD_FPEXC_MODE(r5) | ||
| 67 | ori r9,r9,MSR_FP /* enable FP for current */ | ||
| 68 | or r9,r9,r4 | ||
| 69 | lfd fr0,THREAD_FPSCR-4(r5) | ||
| 70 | mtfsf 0xff,fr0 | ||
| 71 | REST_32FPRS(0, r5) | ||
| 72 | #ifndef CONFIG_SMP | ||
| 73 | subi r4,r5,THREAD | ||
| 74 | sub r4,r4,r6 | ||
| 75 | stw r4,last_task_used_math@l(r3) | ||
| 76 | #endif /* CONFIG_SMP */ | ||
| 77 | /* restore registers and return */ | ||
| 78 | /* we haven't used ctr or xer or lr */ | ||
| 79 | b fast_exception_return | ||
| 80 | |||
| 81 | /* | ||
| 82 | * FP unavailable trap from kernel - print a message, but let | ||
| 83 | * the task use FP in the kernel until it returns to user mode. | ||
| 84 | */ | ||
| 85 | .globl KernelFP | ||
| 86 | KernelFP: | ||
| 87 | lwz r3,_MSR(r1) | ||
| 88 | ori r3,r3,MSR_FP | ||
| 89 | stw r3,_MSR(r1) /* enable use of FP after return */ | ||
| 90 | lis r3,86f@h | ||
| 91 | ori r3,r3,86f@l | ||
| 92 | mr r4,r2 /* current */ | ||
| 93 | lwz r5,_NIP(r1) | ||
| 94 | bl printk | ||
| 95 | b ret_from_except | ||
| 96 | 86: .string "floating point used in kernel (task=%p, pc=%x)\n" | ||
| 97 | .align 4,0 | ||
| 98 | |||
| 99 | /* | ||
| 100 | * giveup_fpu(tsk) | ||
| 101 | * Disable FP for the task given as the argument, | ||
| 102 | * and save the floating-point registers in its thread_struct. | ||
| 103 | * Enables the FPU for use in the kernel on return. | ||
| 104 | */ | ||
| 105 | .globl giveup_fpu | ||
| 106 | giveup_fpu: | ||
| 107 | mfmsr r5 | ||
| 108 | ori r5,r5,MSR_FP | ||
| 109 | SYNC_601 | ||
| 110 | ISYNC_601 | ||
| 111 | MTMSRD(r5) /* enable use of fpu now */ | ||
| 112 | SYNC_601 | ||
| 113 | isync | ||
| 114 | cmpwi 0,r3,0 | ||
| 115 | beqlr- /* if no previous owner, done */ | ||
| 116 | addi r3,r3,THREAD /* want THREAD of task */ | ||
| 117 | lwz r5,PT_REGS(r3) | ||
| 118 | cmpwi 0,r5,0 | ||
| 119 | SAVE_32FPRS(0, r3) | ||
| 120 | mffs fr0 | ||
| 121 | stfd fr0,THREAD_FPSCR-4(r3) | ||
| 122 | beq 1f | ||
| 123 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 124 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | ||
| 125 | andc r4,r4,r3 /* disable FP for previous task */ | ||
| 126 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 127 | 1: | ||
| 128 | #ifndef CONFIG_SMP | ||
| 129 | li r5,0 | ||
| 130 | lis r4,last_task_used_math@ha | ||
| 131 | stw r5,last_task_used_math@l(r4) | ||
| 132 | #endif /* CONFIG_SMP */ | ||
| 133 | blr | ||
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 1a89a71e0acc..a931d773715f 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S | |||
| @@ -775,133 +775,6 @@ InstructionSegment: | |||
| 775 | EXC_XFER_STD(0x480, UnknownException) | 775 | EXC_XFER_STD(0x480, UnknownException) |
| 776 | #endif /* CONFIG_PPC64BRIDGE */ | 776 | #endif /* CONFIG_PPC64BRIDGE */ |
| 777 | 777 | ||
| 778 | /* | ||
| 779 | * This task wants to use the FPU now. | ||
| 780 | * On UP, disable FP for the task which had the FPU previously, | ||
| 781 | * and save its floating-point registers in its thread_struct. | ||
| 782 | * Load up this task's FP registers from its thread_struct, | ||
| 783 | * enable the FPU for the current task and return to the task. | ||
| 784 | */ | ||
| 785 | load_up_fpu: | ||
| 786 | mfmsr r5 | ||
| 787 | ori r5,r5,MSR_FP | ||
| 788 | #ifdef CONFIG_PPC64BRIDGE | ||
| 789 | clrldi r5,r5,1 /* turn off 64-bit mode */ | ||
| 790 | #endif /* CONFIG_PPC64BRIDGE */ | ||
| 791 | SYNC | ||
| 792 | MTMSRD(r5) /* enable use of fpu now */ | ||
| 793 | isync | ||
| 794 | /* | ||
| 795 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
| 796 | * horrendously complex, especially when a task switches from one CPU | ||
| 797 | * to another. Instead we call giveup_fpu in switch_to. | ||
| 798 | */ | ||
| 799 | #ifndef CONFIG_SMP | ||
| 800 | tophys(r6,0) /* get __pa constant */ | ||
| 801 | addis r3,r6,last_task_used_math@ha | ||
| 802 | lwz r4,last_task_used_math@l(r3) | ||
| 803 | cmpwi 0,r4,0 | ||
| 804 | beq 1f | ||
| 805 | add r4,r4,r6 | ||
| 806 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | ||
| 807 | SAVE_32FPRS(0, r4) | ||
| 808 | mffs fr0 | ||
| 809 | stfd fr0,THREAD_FPSCR-4(r4) | ||
| 810 | lwz r5,PT_REGS(r4) | ||
| 811 | add r5,r5,r6 | ||
| 812 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 813 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | ||
| 814 | andc r4,r4,r10 /* disable FP for previous task */ | ||
| 815 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 816 | 1: | ||
| 817 | #endif /* CONFIG_SMP */ | ||
| 818 | /* enable use of FP after return */ | ||
| 819 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | ||
| 820 | lwz r4,THREAD_FPEXC_MODE(r5) | ||
| 821 | ori r9,r9,MSR_FP /* enable FP for current */ | ||
| 822 | or r9,r9,r4 | ||
| 823 | lfd fr0,THREAD_FPSCR-4(r5) | ||
| 824 | mtfsf 0xff,fr0 | ||
| 825 | REST_32FPRS(0, r5) | ||
| 826 | #ifndef CONFIG_SMP | ||
| 827 | subi r4,r5,THREAD | ||
| 828 | sub r4,r4,r6 | ||
| 829 | stw r4,last_task_used_math@l(r3) | ||
| 830 | #endif /* CONFIG_SMP */ | ||
| 831 | /* restore registers and return */ | ||
| 832 | /* we haven't used ctr or xer or lr */ | ||
| 833 | /* fall through to fast_exception_return */ | ||
| 834 | |||
| 835 | .globl fast_exception_return | ||
| 836 | fast_exception_return: | ||
| 837 | andi. r10,r9,MSR_RI /* check for recoverable interrupt */ | ||
| 838 | beq 1f /* if not, we've got problems */ | ||
| 839 | 2: REST_4GPRS(3, r11) | ||
| 840 | lwz r10,_CCR(r11) | ||
| 841 | REST_GPR(1, r11) | ||
| 842 | mtcr r10 | ||
| 843 | lwz r10,_LINK(r11) | ||
| 844 | mtlr r10 | ||
| 845 | REST_GPR(10, r11) | ||
| 846 | mtspr SPRN_SRR1,r9 | ||
| 847 | mtspr SPRN_SRR0,r12 | ||
| 848 | REST_GPR(9, r11) | ||
| 849 | REST_GPR(12, r11) | ||
| 850 | lwz r11,GPR11(r11) | ||
| 851 | SYNC | ||
| 852 | RFI | ||
| 853 | |||
| 854 | /* check if the exception happened in a restartable section */ | ||
| 855 | 1: lis r3,exc_exit_restart_end@ha | ||
| 856 | addi r3,r3,exc_exit_restart_end@l | ||
| 857 | cmplw r12,r3 | ||
| 858 | bge 3f | ||
| 859 | lis r4,exc_exit_restart@ha | ||
| 860 | addi r4,r4,exc_exit_restart@l | ||
| 861 | cmplw r12,r4 | ||
| 862 | blt 3f | ||
| 863 | lis r3,fee_restarts@ha | ||
| 864 | tophys(r3,r3) | ||
| 865 | lwz r5,fee_restarts@l(r3) | ||
| 866 | addi r5,r5,1 | ||
| 867 | stw r5,fee_restarts@l(r3) | ||
| 868 | mr r12,r4 /* restart at exc_exit_restart */ | ||
| 869 | b 2b | ||
| 870 | |||
| 871 | .comm fee_restarts,4 | ||
| 872 | |||
| 873 | /* aargh, a nonrecoverable interrupt, panic */ | ||
| 874 | /* aargh, we don't know which trap this is */ | ||
| 875 | /* but the 601 doesn't implement the RI bit, so assume it's OK */ | ||
| 876 | 3: | ||
| 877 | BEGIN_FTR_SECTION | ||
| 878 | b 2b | ||
| 879 | END_FTR_SECTION_IFSET(CPU_FTR_601) | ||
| 880 | li r10,-1 | ||
| 881 | stw r10,TRAP(r11) | ||
| 882 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 883 | li r10,MSR_KERNEL | ||
| 884 | bl transfer_to_handler_full | ||
| 885 | .long nonrecoverable_exception | ||
| 886 | .long ret_from_except | ||
| 887 | |||
| 888 | /* | ||
| 889 | * FP unavailable trap from kernel - print a message, but let | ||
| 890 | * the task use FP in the kernel until it returns to user mode. | ||
| 891 | */ | ||
| 892 | KernelFP: | ||
| 893 | lwz r3,_MSR(r1) | ||
| 894 | ori r3,r3,MSR_FP | ||
| 895 | stw r3,_MSR(r1) /* enable use of FP after return */ | ||
| 896 | lis r3,86f@h | ||
| 897 | ori r3,r3,86f@l | ||
| 898 | mr r4,r2 /* current */ | ||
| 899 | lwz r5,_NIP(r1) | ||
| 900 | bl printk | ||
| 901 | b ret_from_except | ||
| 902 | 86: .string "floating point used in kernel (task=%p, pc=%x)\n" | ||
| 903 | .align 4,0 | ||
| 904 | |||
| 905 | #ifdef CONFIG_ALTIVEC | 778 | #ifdef CONFIG_ALTIVEC |
| 906 | /* Note that the AltiVec support is closely modeled after the FP | 779 | /* Note that the AltiVec support is closely modeled after the FP |
| 907 | * support. Changes to one are likely to be applicable to the | 780 | * support. Changes to one are likely to be applicable to the |
| @@ -1016,42 +889,6 @@ giveup_altivec: | |||
| 1016 | #endif /* CONFIG_ALTIVEC */ | 889 | #endif /* CONFIG_ALTIVEC */ |
| 1017 | 890 | ||
| 1018 | /* | 891 | /* |
| 1019 | * giveup_fpu(tsk) | ||
| 1020 | * Disable FP for the task given as the argument, | ||
| 1021 | * and save the floating-point registers in its thread_struct. | ||
| 1022 | * Enables the FPU for use in the kernel on return. | ||
| 1023 | */ | ||
| 1024 | .globl giveup_fpu | ||
| 1025 | giveup_fpu: | ||
| 1026 | mfmsr r5 | ||
| 1027 | ori r5,r5,MSR_FP | ||
| 1028 | SYNC_601 | ||
| 1029 | ISYNC_601 | ||
| 1030 | MTMSRD(r5) /* enable use of fpu now */ | ||
| 1031 | SYNC_601 | ||
| 1032 | isync | ||
| 1033 | cmpwi 0,r3,0 | ||
| 1034 | beqlr- /* if no previous owner, done */ | ||
| 1035 | addi r3,r3,THREAD /* want THREAD of task */ | ||
| 1036 | lwz r5,PT_REGS(r3) | ||
| 1037 | cmpwi 0,r5,0 | ||
| 1038 | SAVE_32FPRS(0, r3) | ||
| 1039 | mffs fr0 | ||
| 1040 | stfd fr0,THREAD_FPSCR-4(r3) | ||
| 1041 | beq 1f | ||
| 1042 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 1043 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | ||
| 1044 | andc r4,r4,r3 /* disable FP for previous task */ | ||
| 1045 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
| 1046 | 1: | ||
| 1047 | #ifndef CONFIG_SMP | ||
| 1048 | li r5,0 | ||
| 1049 | lis r4,last_task_used_math@ha | ||
| 1050 | stw r5,last_task_used_math@l(r4) | ||
| 1051 | #endif /* CONFIG_SMP */ | ||
| 1052 | blr | ||
| 1053 | |||
| 1054 | /* | ||
| 1055 | * This code is jumped to from the startup code to copy | 892 | * This code is jumped to from the startup code to copy |
| 1056 | * the kernel image to physical address 0. | 893 | * the kernel image to physical address 0. |
| 1057 | */ | 894 | */ |
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 9ed8165a3d6c..9b6a8e513657 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S | |||
| @@ -426,7 +426,11 @@ interrupt_base: | |||
| 426 | PROGRAM_EXCEPTION | 426 | PROGRAM_EXCEPTION |
| 427 | 427 | ||
| 428 | /* Floating Point Unavailable Interrupt */ | 428 | /* Floating Point Unavailable Interrupt */ |
| 429 | #ifdef CONFIG_PPC_FPU | ||
| 430 | FP_UNAVAILABLE_EXCEPTION | ||
| 431 | #else | ||
| 429 | EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) | 432 | EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) |
| 433 | #endif | ||
| 430 | 434 | ||
| 431 | /* System Call Interrupt */ | 435 | /* System Call Interrupt */ |
| 432 | START_EXCEPTION(SystemCall) | 436 | START_EXCEPTION(SystemCall) |
| @@ -686,8 +690,10 @@ _GLOBAL(giveup_altivec) | |||
| 686 | * | 690 | * |
| 687 | * The 44x core does not have an FPU. | 691 | * The 44x core does not have an FPU. |
| 688 | */ | 692 | */ |
| 693 | #ifndef CONFIG_PPC_FPU | ||
| 689 | _GLOBAL(giveup_fpu) | 694 | _GLOBAL(giveup_fpu) |
| 690 | blr | 695 | blr |
| 696 | #endif | ||
| 691 | 697 | ||
| 692 | /* | 698 | /* |
| 693 | * extern void abort(void) | 699 | * extern void abort(void) |
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index 884dac916bce..f213d12eec08 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h | |||
| @@ -337,4 +337,11 @@ label: | |||
| 337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
| 338 | EXC_XFER_LITE(0x0900, timer_interrupt) | 338 | EXC_XFER_LITE(0x0900, timer_interrupt) |
| 339 | 339 | ||
| 340 | #define FP_UNAVAILABLE_EXCEPTION \ | ||
| 341 | START_EXCEPTION(FloatingPointUnavailable) \ | ||
| 342 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 343 | bne load_up_fpu; /* if from user, just load it up */ \ | ||
| 344 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 345 | EXC_XFER_EE_LITE(0x800, KernelFP) | ||
| 346 | |||
| 340 | #endif /* __HEAD_BOOKE_H__ */ | 347 | #endif /* __HEAD_BOOKE_H__ */ |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index d64bf61d2b1f..f22ddce36135 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
| @@ -504,7 +504,11 @@ interrupt_base: | |||
| 504 | PROGRAM_EXCEPTION | 504 | PROGRAM_EXCEPTION |
| 505 | 505 | ||
| 506 | /* Floating Point Unavailable Interrupt */ | 506 | /* Floating Point Unavailable Interrupt */ |
| 507 | #ifdef CONFIG_PPC_FPU | ||
| 508 | FP_UNAVAILABLE_EXCEPTION | ||
| 509 | #else | ||
| 507 | EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) | 510 | EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) |
| 511 | #endif | ||
| 508 | 512 | ||
| 509 | /* System Call Interrupt */ | 513 | /* System Call Interrupt */ |
| 510 | START_EXCEPTION(SystemCall) | 514 | START_EXCEPTION(SystemCall) |
| @@ -916,10 +920,12 @@ _GLOBAL(giveup_spe) | |||
| 916 | /* | 920 | /* |
| 917 | * extern void giveup_fpu(struct task_struct *prev) | 921 | * extern void giveup_fpu(struct task_struct *prev) |
| 918 | * | 922 | * |
| 919 | * The e500 core does not have an FPU. | 923 | * Not all FSL Book-E cores have an FPU |
| 920 | */ | 924 | */ |
| 925 | #ifndef CONFIG_PPC_FPU | ||
| 921 | _GLOBAL(giveup_fpu) | 926 | _GLOBAL(giveup_fpu) |
| 922 | blr | 927 | blr |
| 928 | #endif | ||
| 923 | 929 | ||
| 924 | /* | 930 | /* |
| 925 | * extern void abort(void) | 931 | * extern void abort(void) |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 73f7c23b0dd4..e4f1615ec13f 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
| @@ -1096,17 +1096,7 @@ _GLOBAL(_get_SP) | |||
| 1096 | * and exceptions as if the cpu had performed the load or store. | 1096 | * and exceptions as if the cpu had performed the load or store. |
| 1097 | */ | 1097 | */ |
| 1098 | 1098 | ||
| 1099 | #if defined(CONFIG_4xx) || defined(CONFIG_E500) | 1099 | #ifdef CONFIG_PPC_FPU |
| 1100 | _GLOBAL(cvt_fd) | ||
| 1101 | lfs 0,0(r3) | ||
| 1102 | stfd 0,0(r4) | ||
| 1103 | blr | ||
| 1104 | |||
| 1105 | _GLOBAL(cvt_df) | ||
| 1106 | lfd 0,0(r3) | ||
| 1107 | stfs 0,0(r4) | ||
| 1108 | blr | ||
| 1109 | #else | ||
| 1110 | _GLOBAL(cvt_fd) | 1100 | _GLOBAL(cvt_fd) |
| 1111 | lfd 0,-4(r5) /* load up fpscr value */ | 1101 | lfd 0,-4(r5) /* load up fpscr value */ |
| 1112 | mtfsf 0xff,0 | 1102 | mtfsf 0xff,0 |
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 426b6f7d9de3..59d59a8dc249 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
| 27 | #include <linux/user.h> | 27 | #include <linux/user.h> |
| 28 | #include <linux/security.h> | 28 | #include <linux/security.h> |
| 29 | #include <linux/signal.h> | ||
| 29 | 30 | ||
| 30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
| 31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
| @@ -356,7 +357,7 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
| 356 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | 357 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ |
| 357 | case PTRACE_CONT: { /* restart after signal. */ | 358 | case PTRACE_CONT: { /* restart after signal. */ |
| 358 | ret = -EIO; | 359 | ret = -EIO; |
| 359 | if ((unsigned long) data > _NSIG) | 360 | if (!valid_signal(data)) |
| 360 | break; | 361 | break; |
| 361 | if (request == PTRACE_SYSCALL) { | 362 | if (request == PTRACE_SYSCALL) { |
| 362 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 363 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| @@ -389,7 +390,7 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
| 389 | 390 | ||
| 390 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | 391 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ |
| 391 | ret = -EIO; | 392 | ret = -EIO; |
| 392 | if ((unsigned long) data > _NSIG) | 393 | if (!valid_signal(data)) |
| 393 | break; | 394 | break; |
| 394 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 395 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 395 | set_single_step(child); | 396 | set_single_step(child); |
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 361865c4bc84..f8e7e324a173 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
| @@ -176,7 +176,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
| 176 | #else | 176 | #else |
| 177 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) | 177 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) |
| 178 | #endif | 178 | #endif |
| 179 | #define REASON_FP 0 | 179 | #define REASON_FP ESR_FP |
| 180 | #define REASON_ILLEGAL ESR_PIL | 180 | #define REASON_ILLEGAL ESR_PIL |
| 181 | #define REASON_PRIVILEGED ESR_PPR | 181 | #define REASON_PRIVILEGED ESR_PPR |
| 182 | #define REASON_TRAP ESR_PTR | 182 | #define REASON_TRAP ESR_PTR |
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S index da34a9bc9299..fb977de6b704 100644 --- a/arch/ppc/platforms/pmac_cache.S +++ b/arch/ppc/platforms/pmac_cache.S | |||
| @@ -64,27 +64,39 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 64 | mtspr SPRN_HID0,r4 /* Disable DPM */ | 64 | mtspr SPRN_HID0,r4 /* Disable DPM */ |
| 65 | sync | 65 | sync |
| 66 | 66 | ||
| 67 | /* disp-flush L1 */ | 67 | /* Disp-flush L1. We have a weird problem here that I never |
| 68 | li r4,0x4000 | 68 | * totally figured out. On 750FX, using the ROM for the flush |
| 69 | mtctr r4 | 69 | * results in a non-working flush. We use that workaround for |
| 70 | * now until I finally understand what's going on. --BenH | ||
| 71 | */ | ||
| 72 | |||
| 73 | /* ROM base by default */ | ||
| 70 | lis r4,0xfff0 | 74 | lis r4,0xfff0 |
| 71 | 1: lwzx r0,r0,r4 | 75 | mfpvr r3 |
| 76 | srwi r3,r3,16 | ||
| 77 | cmplwi cr0,r3,0x7000 | ||
| 78 | bne+ 1f | ||
| 79 | /* RAM base on 750FX */ | ||
| 80 | li r4,0 | ||
| 81 | 1: li r4,0x4000 | ||
| 82 | mtctr r4 | ||
| 83 | 1: lwz r0,0(r4) | ||
| 72 | addi r4,r4,32 | 84 | addi r4,r4,32 |
| 73 | bdnz 1b | 85 | bdnz 1b |
| 74 | sync | 86 | sync |
| 75 | isync | 87 | isync |
| 76 | 88 | ||
| 77 | /* disable / invalidate / enable L1 data */ | 89 | /* Disable / invalidate / enable L1 data */ |
| 78 | mfspr r3,SPRN_HID0 | 90 | mfspr r3,SPRN_HID0 |
| 79 | rlwinm r0,r0,0,~HID0_DCE | 91 | rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE) |
| 80 | mtspr SPRN_HID0,r3 | 92 | mtspr SPRN_HID0,r3 |
| 81 | sync | 93 | sync |
| 82 | isync | 94 | isync |
| 83 | ori r3,r3,HID0_DCE|HID0_DCI | 95 | ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI) |
| 84 | sync | 96 | sync |
| 85 | isync | 97 | isync |
| 86 | mtspr SPRN_HID0,r3 | 98 | mtspr SPRN_HID0,r3 |
| 87 | xori r3,r3,HID0_DCI | 99 | xori r3,r3,(HID0_DCI|HID0_ICFI) |
| 88 | mtspr SPRN_HID0,r3 | 100 | mtspr SPRN_HID0,r3 |
| 89 | sync | 101 | sync |
| 90 | 102 | ||
| @@ -110,11 +122,20 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 110 | lis r4,2 | 122 | lis r4,2 |
| 111 | mtctr r4 | 123 | mtctr r4 |
| 112 | lis r4,0xfff0 | 124 | lis r4,0xfff0 |
| 113 | 1: lwzx r0,r0,r4 | 125 | 1: lwz r0,0(r4) |
| 126 | addi r4,r4,32 | ||
| 127 | bdnz 1b | ||
| 128 | sync | ||
| 129 | isync | ||
| 130 | lis r4,2 | ||
| 131 | mtctr r4 | ||
| 132 | lis r4,0xfff0 | ||
| 133 | 1: dcbf 0,r4 | ||
| 114 | addi r4,r4,32 | 134 | addi r4,r4,32 |
| 115 | bdnz 1b | 135 | bdnz 1b |
| 116 | sync | 136 | sync |
| 117 | isync | 137 | isync |
| 138 | |||
| 118 | /* now disable L2 */ | 139 | /* now disable L2 */ |
| 119 | rlwinm r5,r5,0,~L2CR_L2E | 140 | rlwinm r5,r5,0,~L2CR_L2E |
| 120 | b 2f | 141 | b 2f |
| @@ -135,6 +156,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 135 | mtspr SPRN_L2CR,r4 | 156 | mtspr SPRN_L2CR,r4 |
| 136 | sync | 157 | sync |
| 137 | isync | 158 | isync |
| 159 | |||
| 160 | /* Wait for the invalidation to complete */ | ||
| 161 | 1: mfspr r3,SPRN_L2CR | ||
| 162 | rlwinm. r0,r3,0,31,31 | ||
| 163 | bne 1b | ||
| 164 | |||
| 165 | /* Clear L2I */ | ||
| 138 | xoris r4,r4,L2CR_L2I@h | 166 | xoris r4,r4,L2CR_L2I@h |
| 139 | sync | 167 | sync |
| 140 | mtspr SPRN_L2CR,r4 | 168 | mtspr SPRN_L2CR,r4 |
| @@ -142,14 +170,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 142 | 170 | ||
| 143 | /* now disable the L1 data cache */ | 171 | /* now disable the L1 data cache */ |
| 144 | mfspr r0,SPRN_HID0 | 172 | mfspr r0,SPRN_HID0 |
| 145 | rlwinm r0,r0,0,~HID0_DCE | 173 | rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE) |
| 146 | mtspr SPRN_HID0,r0 | 174 | mtspr SPRN_HID0,r0 |
| 147 | sync | 175 | sync |
| 148 | isync | 176 | isync |
| 149 | 177 | ||
| 150 | /* Restore HID0[DPM] to whatever it was before */ | 178 | /* Restore HID0[DPM] to whatever it was before */ |
| 151 | sync | 179 | sync |
| 152 | mtspr SPRN_HID0,r8 | 180 | mfspr r0,SPRN_HID0 |
| 181 | rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */ | ||
| 182 | mtspr SPRN_HID0,r0 | ||
| 153 | sync | 183 | sync |
| 154 | 184 | ||
| 155 | /* restore DR and EE */ | 185 | /* restore DR and EE */ |
| @@ -201,7 +231,7 @@ flush_disable_745x: | |||
| 201 | mtctr r4 | 231 | mtctr r4 |
| 202 | li r4,0 | 232 | li r4,0 |
| 203 | 1: | 233 | 1: |
| 204 | lwzx r0,r0,r4 | 234 | lwz r0,0(r4) |
| 205 | addi r4,r4,32 /* Go to start of next cache line */ | 235 | addi r4,r4,32 /* Go to start of next cache line */ |
| 206 | bdnz 1b | 236 | bdnz 1b |
| 207 | isync | 237 | isync |
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 46cbf36722db..867336ad5d36 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c | |||
| @@ -1590,6 +1590,114 @@ intrepid_shutdown(struct macio_chip* macio, int sleep_mode) | |||
| 1590 | mdelay(10); | 1590 | mdelay(10); |
| 1591 | } | 1591 | } |
| 1592 | 1592 | ||
| 1593 | |||
| 1594 | void __pmac pmac_tweak_clock_spreading(int enable) | ||
| 1595 | { | ||
| 1596 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1597 | |||
| 1598 | /* Hack for doing clock spreading on some machines PowerBooks and | ||
| 1599 | * iBooks. This implements the "platform-do-clockspreading" OF | ||
| 1600 | * property as decoded manually on various models. For safety, we also | ||
| 1601 | * check the product ID in the device-tree in cases we'll whack the i2c | ||
| 1602 | * chip to make reasonably sure we won't set wrong values in there | ||
| 1603 | * | ||
| 1604 | * Of course, ultimately, we have to implement a real parser for | ||
| 1605 | * the platform-do-* stuff... | ||
| 1606 | */ | ||
| 1607 | |||
| 1608 | if (macio->type == macio_intrepid) { | ||
| 1609 | if (enable) | ||
| 1610 | UN_OUT(UNI_N_CLOCK_SPREADING, 2); | ||
| 1611 | else | ||
| 1612 | UN_OUT(UNI_N_CLOCK_SPREADING, 0); | ||
| 1613 | mdelay(40); | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | while (machine_is_compatible("PowerBook5,2") || | ||
| 1617 | machine_is_compatible("PowerBook5,3") || | ||
| 1618 | machine_is_compatible("PowerBook6,2") || | ||
| 1619 | machine_is_compatible("PowerBook6,3")) { | ||
| 1620 | struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); | ||
| 1621 | struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); | ||
| 1622 | u8 buffer[9]; | ||
| 1623 | u32 *productID; | ||
| 1624 | int i, rc, changed = 0; | ||
| 1625 | |||
| 1626 | if (dt == NULL) | ||
| 1627 | break; | ||
| 1628 | productID = (u32 *)get_property(dt, "pid#", NULL); | ||
| 1629 | if (productID == NULL) | ||
| 1630 | break; | ||
| 1631 | while(ui2c) { | ||
| 1632 | struct device_node *p = of_get_parent(ui2c); | ||
| 1633 | if (p && !strcmp(p->name, "uni-n")) | ||
| 1634 | break; | ||
| 1635 | ui2c = of_find_node_by_type(ui2c, "i2c"); | ||
| 1636 | } | ||
| 1637 | if (ui2c == NULL) | ||
| 1638 | break; | ||
| 1639 | DBG("Trying to bump clock speed for PID: %08x...\n", *productID); | ||
| 1640 | rc = pmac_low_i2c_open(ui2c, 1); | ||
| 1641 | if (rc != 0) | ||
| 1642 | break; | ||
| 1643 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 1644 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 1645 | DBG("read result: %d,", rc); | ||
| 1646 | if (rc != 0) { | ||
| 1647 | pmac_low_i2c_close(ui2c); | ||
| 1648 | break; | ||
| 1649 | } | ||
| 1650 | for (i=0; i<9; i++) | ||
| 1651 | DBG(" %02x", buffer[i]); | ||
| 1652 | DBG("\n"); | ||
| 1653 | |||
| 1654 | switch(*productID) { | ||
| 1655 | case 0x1182: /* AlBook 12" rev 2 */ | ||
| 1656 | case 0x1183: /* iBook G4 12" */ | ||
| 1657 | buffer[0] = (buffer[0] & 0x8f) | 0x70; | ||
| 1658 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 1659 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 1660 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 1661 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba); | ||
| 1662 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 1663 | changed = 1; | ||
| 1664 | break; | ||
| 1665 | case 0x3142: /* AlBook 15" (ATI M10) */ | ||
| 1666 | case 0x3143: /* AlBook 17" (ATI M10) */ | ||
| 1667 | buffer[0] = (buffer[0] & 0xaf) | 0x50; | ||
| 1668 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 1669 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 1670 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 1671 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0); | ||
| 1672 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 1673 | changed = 1; | ||
| 1674 | break; | ||
| 1675 | default: | ||
| 1676 | DBG("i2c-hwclock: Machine model not handled\n"); | ||
| 1677 | break; | ||
| 1678 | } | ||
| 1679 | if (!changed) { | ||
| 1680 | pmac_low_i2c_close(ui2c); | ||
| 1681 | break; | ||
| 1682 | } | ||
| 1683 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); | ||
| 1684 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); | ||
| 1685 | DBG("write result: %d,", rc); | ||
| 1686 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 1687 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 1688 | DBG("read result: %d,", rc); | ||
| 1689 | if (rc != 0) { | ||
| 1690 | pmac_low_i2c_close(ui2c); | ||
| 1691 | break; | ||
| 1692 | } | ||
| 1693 | for (i=0; i<9; i++) | ||
| 1694 | DBG(" %02x", buffer[i]); | ||
| 1695 | pmac_low_i2c_close(ui2c); | ||
| 1696 | break; | ||
| 1697 | } | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | |||
| 1593 | static int __pmac | 1701 | static int __pmac |
| 1594 | core99_sleep(void) | 1702 | core99_sleep(void) |
| 1595 | { | 1703 | { |
| @@ -1601,12 +1709,6 @@ core99_sleep(void) | |||
| 1601 | macio->type != macio_intrepid) | 1709 | macio->type != macio_intrepid) |
| 1602 | return -ENODEV; | 1710 | return -ENODEV; |
| 1603 | 1711 | ||
| 1604 | /* The device-tree contains that in the hwclock node */ | ||
| 1605 | if (macio->type == macio_intrepid) { | ||
| 1606 | UN_OUT(UNI_N_CLOCK_SPREADING, 0); | ||
| 1607 | mdelay(40); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | /* We power off the wireless slot in case it was not done | 1712 | /* We power off the wireless slot in case it was not done |
| 1611 | * by the driver. We don't power it on automatically however | 1713 | * by the driver. We don't power it on automatically however |
| 1612 | */ | 1714 | */ |
| @@ -1749,12 +1851,6 @@ core99_wake_up(void) | |||
| 1749 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); | 1851 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); |
| 1750 | udelay(100); | 1852 | udelay(100); |
| 1751 | 1853 | ||
| 1752 | /* Restore clock spreading */ | ||
| 1753 | if (macio->type == macio_intrepid) { | ||
| 1754 | UN_OUT(UNI_N_CLOCK_SPREADING, 2); | ||
| 1755 | mdelay(40); | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | return 0; | 1854 | return 0; |
| 1759 | } | 1855 | } |
| 1760 | 1856 | ||
| @@ -2149,7 +2245,7 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { | |||
| 2149 | }, | 2245 | }, |
| 2150 | { "PowerBook1,1", "PowerBook 101 (Lombard)", | 2246 | { "PowerBook1,1", "PowerBook 101 (Lombard)", |
| 2151 | PMAC_TYPE_101_PBOOK, paddington_features, | 2247 | PMAC_TYPE_101_PBOOK, paddington_features, |
| 2152 | PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE | 2248 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE |
| 2153 | }, | 2249 | }, |
| 2154 | { "PowerBook2,1", "iBook (first generation)", | 2250 | { "PowerBook2,1", "iBook (first generation)", |
| 2155 | PMAC_TYPE_ORIG_IBOOK, core99_features, | 2251 | PMAC_TYPE_ORIG_IBOOK, core99_features, |
| @@ -2718,97 +2814,11 @@ set_initial_features(void) | |||
| 2718 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | 2814 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); |
| 2719 | } | 2815 | } |
| 2720 | 2816 | ||
| 2721 | /* Hack for bumping clock speed on the new PowerBooks and the | 2817 | /* Some machine models need the clock chip to be properly setup for |
| 2722 | * iBook G4. This implements the "platform-do-clockspreading" OF | 2818 | * clock spreading now. This should be a platform function but we |
| 2723 | * property. For safety, we also check the product ID in the | 2819 | * don't do these at the moment |
| 2724 | * device-tree to make reasonably sure we won't set wrong values | ||
| 2725 | * in the clock chip. | ||
| 2726 | * | ||
| 2727 | * Of course, ultimately, we have to implement a real parser for | ||
| 2728 | * the platform-do-* stuff... | ||
| 2729 | */ | 2820 | */ |
| 2730 | while (machine_is_compatible("PowerBook5,2") || | 2821 | pmac_tweak_clock_spreading(1); |
| 2731 | machine_is_compatible("PowerBook5,3") || | ||
| 2732 | machine_is_compatible("PowerBook6,2") || | ||
| 2733 | machine_is_compatible("PowerBook6,3")) { | ||
| 2734 | struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); | ||
| 2735 | struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); | ||
| 2736 | u8 buffer[9]; | ||
| 2737 | u32 *productID; | ||
| 2738 | int i, rc, changed = 0; | ||
| 2739 | |||
| 2740 | if (dt == NULL) | ||
| 2741 | break; | ||
| 2742 | productID = (u32 *)get_property(dt, "pid#", NULL); | ||
| 2743 | if (productID == NULL) | ||
| 2744 | break; | ||
| 2745 | while(ui2c) { | ||
| 2746 | struct device_node *p = of_get_parent(ui2c); | ||
| 2747 | if (p && !strcmp(p->name, "uni-n")) | ||
| 2748 | break; | ||
| 2749 | ui2c = of_find_node_by_type(ui2c, "i2c"); | ||
| 2750 | } | ||
| 2751 | if (ui2c == NULL) | ||
| 2752 | break; | ||
| 2753 | DBG("Trying to bump clock speed for PID: %08x...\n", *productID); | ||
| 2754 | rc = pmac_low_i2c_open(ui2c, 1); | ||
| 2755 | if (rc != 0) | ||
| 2756 | break; | ||
| 2757 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 2758 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 2759 | DBG("read result: %d,", rc); | ||
| 2760 | if (rc != 0) { | ||
| 2761 | pmac_low_i2c_close(ui2c); | ||
| 2762 | break; | ||
| 2763 | } | ||
| 2764 | for (i=0; i<9; i++) | ||
| 2765 | DBG(" %02x", buffer[i]); | ||
| 2766 | DBG("\n"); | ||
| 2767 | |||
| 2768 | switch(*productID) { | ||
| 2769 | case 0x1182: /* AlBook 12" rev 2 */ | ||
| 2770 | case 0x1183: /* iBook G4 12" */ | ||
| 2771 | buffer[0] = (buffer[0] & 0x8f) | 0x70; | ||
| 2772 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 2773 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 2774 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 2775 | buffer[7] = (buffer[7] & 0x00) | 0xc0; | ||
| 2776 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 2777 | changed = 1; | ||
| 2778 | break; | ||
| 2779 | case 0x3142: /* AlBook 15" (ATI M10) */ | ||
| 2780 | case 0x3143: /* AlBook 17" (ATI M10) */ | ||
| 2781 | buffer[0] = (buffer[0] & 0xaf) | 0x50; | ||
| 2782 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 2783 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 2784 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 2785 | buffer[7] = (buffer[7] & 0x00) | 0xd0; | ||
| 2786 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 2787 | changed = 1; | ||
| 2788 | break; | ||
| 2789 | default: | ||
| 2790 | DBG("i2c-hwclock: Machine model not handled\n"); | ||
| 2791 | break; | ||
| 2792 | } | ||
| 2793 | if (!changed) { | ||
| 2794 | pmac_low_i2c_close(ui2c); | ||
| 2795 | break; | ||
| 2796 | } | ||
| 2797 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); | ||
| 2798 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); | ||
| 2799 | DBG("write result: %d,", rc); | ||
| 2800 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 2801 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 2802 | DBG("read result: %d,", rc); | ||
| 2803 | if (rc != 0) { | ||
| 2804 | pmac_low_i2c_close(ui2c); | ||
| 2805 | break; | ||
| 2806 | } | ||
| 2807 | for (i=0; i<9; i++) | ||
| 2808 | DBG(" %02x", buffer[i]); | ||
| 2809 | pmac_low_i2c_close(ui2c); | ||
| 2810 | break; | ||
| 2811 | } | ||
| 2812 | 2822 | ||
| 2813 | #endif /* CONFIG_POWER4 */ | 2823 | #endif /* CONFIG_POWER4 */ |
| 2814 | 2824 | ||
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S index 3139b6766ad3..f459ade1bd63 100644 --- a/arch/ppc/platforms/pmac_sleep.S +++ b/arch/ppc/platforms/pmac_sleep.S | |||
| @@ -267,6 +267,10 @@ grackle_wake_up: | |||
| 267 | /* Restore various CPU config stuffs */ | 267 | /* Restore various CPU config stuffs */ |
| 268 | bl __restore_cpu_setup | 268 | bl __restore_cpu_setup |
| 269 | 269 | ||
| 270 | /* Make sure all FPRs have been initialized */ | ||
| 271 | bl reloc_offset | ||
| 272 | bl __init_fpu_registers | ||
| 273 | |||
| 270 | /* Invalidate & enable L1 cache, we don't care about | 274 | /* Invalidate & enable L1 cache, we don't care about |
| 271 | * whatever the ROM may have tried to write to memory | 275 | * whatever the ROM may have tried to write to memory |
| 272 | */ | 276 | */ |
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 2a99b43737a8..c30607a972d8 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #define PPC7D_RST_PIN 17 /* GPP17 */ | 68 | #define PPC7D_RST_PIN 17 /* GPP17 */ |
| 69 | 69 | ||
| 70 | extern u32 mv64360_irq_base; | 70 | extern u32 mv64360_irq_base; |
| 71 | extern spinlock_t rtc_lock; | ||
| 71 | 72 | ||
| 72 | static struct mv64x60_handle bh; | 73 | static struct mv64x60_handle bh; |
| 73 | static int ppc7d_has_alma; | 74 | static int ppc7d_has_alma; |
| @@ -75,6 +76,11 @@ static int ppc7d_has_alma; | |||
| 75 | extern void gen550_progress(char *, unsigned short); | 76 | extern void gen550_progress(char *, unsigned short); |
| 76 | extern void gen550_init(int, struct uart_port *); | 77 | extern void gen550_init(int, struct uart_port *); |
| 77 | 78 | ||
| 79 | /* FIXME - move to h file */ | ||
| 80 | extern int ds1337_do_command(int id, int cmd, void *arg); | ||
| 81 | #define DS1337_GET_DATE 0 | ||
| 82 | #define DS1337_SET_DATE 1 | ||
| 83 | |||
| 78 | /* residual data */ | 84 | /* residual data */ |
| 79 | unsigned char __res[sizeof(bd_t)]; | 85 | unsigned char __res[sizeof(bd_t)]; |
| 80 | 86 | ||
| @@ -253,6 +259,8 @@ static int ppc7d_show_cpuinfo(struct seq_file *m) | |||
| 253 | u8 val1, val2; | 259 | u8 val1, val2; |
| 254 | static int flash_sizes[4] = { 64, 32, 0, 16 }; | 260 | static int flash_sizes[4] = { 64, 32, 0, 16 }; |
| 255 | static int flash_banks[4] = { 4, 3, 2, 1 }; | 261 | static int flash_banks[4] = { 4, 3, 2, 1 }; |
| 262 | static int sdram_bank_sizes[4] = { 128, 256, 512, 1 }; | ||
| 263 | int sdram_num_banks = 2; | ||
| 256 | static char *pci_modes[] = { "PCI33", "PCI66", | 264 | static char *pci_modes[] = { "PCI33", "PCI66", |
| 257 | "Unknown", "Unknown", | 265 | "Unknown", "Unknown", |
| 258 | "PCIX33", "PCIX66", | 266 | "PCIX33", "PCIX66", |
| @@ -279,13 +287,17 @@ static int ppc7d_show_cpuinfo(struct seq_file *m) | |||
| 279 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 : | 287 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 : |
| 280 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0); | 288 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0); |
| 281 | 289 | ||
| 290 | val = inb(PPC7D_CPLD_MEM_CONFIG); | ||
| 291 | if (val & PPC7D_CPLD_SDRAM_BANK_NUM_MASK) sdram_num_banks--; | ||
| 292 | |||
| 282 | val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND); | 293 | val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND); |
| 283 | val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK; | 294 | val1 = (val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK) >> 6; |
| 284 | seq_printf(m, "SDRAM\t\t: %d%c", | 295 | seq_printf(m, "SDRAM\t\t: %d banks of %d%c, total %d%c", |
| 285 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 : | 296 | sdram_num_banks, |
| 286 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 : | 297 | sdram_bank_sizes[val1], |
| 287 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1, | 298 | (sdram_bank_sizes[val1] < 128) ? 'G' : 'M', |
| 288 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M'); | 299 | sdram_num_banks * sdram_bank_sizes[val1], |
| 300 | (sdram_bank_sizes[val1] < 128) ? 'G' : 'M'); | ||
| 289 | if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) { | 301 | if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) { |
| 290 | seq_printf(m, " [ECC %sabled]", | 302 | seq_printf(m, " [ECC %sabled]", |
| 291 | (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" : | 303 | (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" : |
| @@ -1236,6 +1248,38 @@ static void __init ppc7d_setup_arch(void) | |||
| 1236 | printk(KERN_INFO "Radstone Technology PPC7D\n"); | 1248 | printk(KERN_INFO "Radstone Technology PPC7D\n"); |
| 1237 | if (ppc_md.progress) | 1249 | if (ppc_md.progress) |
| 1238 | ppc_md.progress("ppc7d_setup_arch: exit", 0); | 1250 | ppc_md.progress("ppc7d_setup_arch: exit", 0); |
| 1251 | |||
| 1252 | } | ||
| 1253 | |||
| 1254 | /* Real Time Clock support. | ||
| 1255 | * PPC7D has a DS1337 accessed by I2C. | ||
| 1256 | */ | ||
| 1257 | static ulong ppc7d_get_rtc_time(void) | ||
| 1258 | { | ||
| 1259 | struct rtc_time tm; | ||
| 1260 | int result; | ||
| 1261 | |||
| 1262 | spin_lock(&rtc_lock); | ||
| 1263 | result = ds1337_do_command(0, DS1337_GET_DATE, &tm); | ||
| 1264 | spin_unlock(&rtc_lock); | ||
| 1265 | |||
| 1266 | if (result == 0) | ||
| 1267 | result = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 1268 | |||
| 1269 | return result; | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | static int ppc7d_set_rtc_time(unsigned long nowtime) | ||
| 1273 | { | ||
| 1274 | struct rtc_time tm; | ||
| 1275 | int result; | ||
| 1276 | |||
| 1277 | spin_lock(&rtc_lock); | ||
| 1278 | to_tm(nowtime, &tm); | ||
| 1279 | result = ds1337_do_command(0, DS1337_SET_DATE, &tm); | ||
| 1280 | spin_unlock(&rtc_lock); | ||
| 1281 | |||
| 1282 | return result; | ||
| 1239 | } | 1283 | } |
| 1240 | 1284 | ||
| 1241 | /* This kernel command line parameter can be used to have the target | 1285 | /* This kernel command line parameter can be used to have the target |
| @@ -1293,6 +1337,10 @@ static void ppc7d_init2(void) | |||
| 1293 | data8 |= 0x07; | 1337 | data8 |= 0x07; |
| 1294 | outb(data8, PPC7D_CPLD_LEDS); | 1338 | outb(data8, PPC7D_CPLD_LEDS); |
| 1295 | 1339 | ||
| 1340 | /* Hook up RTC. We couldn't do this earlier because we need the I2C subsystem */ | ||
| 1341 | ppc_md.set_rtc_time = ppc7d_set_rtc_time; | ||
| 1342 | ppc_md.get_rtc_time = ppc7d_get_rtc_time; | ||
| 1343 | |||
| 1296 | pr_debug("%s: exit\n", __FUNCTION__); | 1344 | pr_debug("%s: exit\n", __FUNCTION__); |
| 1297 | } | 1345 | } |
| 1298 | 1346 | ||
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h index 4546fff2b0c3..938375510be4 100644 --- a/arch/ppc/platforms/radstone_ppc7d.h +++ b/arch/ppc/platforms/radstone_ppc7d.h | |||
| @@ -240,6 +240,7 @@ | |||
| 240 | #define PPC7D_CPLD_FLASH_CNTL 0x086E | 240 | #define PPC7D_CPLD_FLASH_CNTL 0x086E |
| 241 | 241 | ||
| 242 | /* MEMORY_CONFIG_EXTEND */ | 242 | /* MEMORY_CONFIG_EXTEND */ |
| 243 | #define PPC7D_CPLD_SDRAM_BANK_NUM_MASK 0x02 | ||
| 243 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK 0xc0 | 244 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK 0xc0 |
| 244 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_128M 0 | 245 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_128M 0 |
| 245 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_256M 0x40 | 246 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_256M 0x40 |
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c index 954b07fc1df3..c867be6981cb 100644 --- a/arch/ppc/syslib/cpm2_pic.c +++ b/arch/ppc/syslib/cpm2_pic.c | |||
| @@ -107,6 +107,11 @@ static void cpm2_end_irq(unsigned int irq_nr) | |||
| 107 | simr = &(cpm2_immr->im_intctl.ic_simrh); | 107 | simr = &(cpm2_immr->im_intctl.ic_simrh); |
| 108 | ppc_cached_irq_mask[word] |= 1 << bit; | 108 | ppc_cached_irq_mask[word] |= 1 << bit; |
| 109 | simr[word] = ppc_cached_irq_mask[word]; | 109 | simr[word] = ppc_cached_irq_mask[word]; |
| 110 | /* | ||
| 111 | * Work around large numbers of spurious IRQs on PowerPC 82xx | ||
| 112 | * systems. | ||
| 113 | */ | ||
| 114 | mb(); | ||
| 110 | } | 115 | } |
| 111 | } | 116 | } |
| 112 | 117 | ||
