diff options
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/Makefile | 7 | ||||
-rw-r--r-- | arch/ppc/kernel/entry.S | 50 | ||||
-rw-r--r-- | arch/ppc/kernel/gemini_pci.c | 6 | ||||
-rw-r--r-- | arch/ppc/kernel/gemini_setup.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/head.S | 8 | ||||
-rw-r--r-- | arch/ppc/kernel/head_4xx.S | 183 | ||||
-rw-r--r-- | arch/ppc/kernel/head_8xx.S | 36 | ||||
-rw-r--r-- | arch/ppc/kernel/irq.c | 6 | ||||
-rw-r--r-- | arch/ppc/kernel/oak_setup.c | 237 | ||||
-rw-r--r-- | arch/ppc/kernel/oak_setup.h | 26 | ||||
-rw-r--r-- | arch/ppc/kernel/open_pic.c | 11 | ||||
-rw-r--r-- | arch/ppc/kernel/open_pic.h | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/pci.c | 80 | ||||
-rw-r--r-- | arch/ppc/kernel/pmac_nvram.c | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/pmac_time.c | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc4xx_pic.c | 204 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc4xx_pic.h | 36 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/ppc/kernel/setup.c | 139 | ||||
-rw-r--r-- | arch/ppc/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/time.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/time.h | 18 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 1 |
24 files changed, 809 insertions, 262 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index a41473fa5..7aaacfadb 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -57,8 +57,11 @@ ifdef CONFIG_SMP O_OBJS += smp.o endif -ifeq ($(CONFIG_OAK),y) - O_OBJS += oak_setup.o +ifeq ($(CONFIG_4xx),y) + O_OBJS += ppc4xx_pic.o + ifeq ($(CONFIG_OAK),y) + O_OBJS += oak_setup.o + endif endif ifeq ($(CONFIG_8xx),y) diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 5ed04344e..cb92163d6 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -265,37 +265,29 @@ _GLOBAL(_switch) SYNC rfi -/* - * ret_from_int(): - * - * Return from an interrupt (external interrupt and - * decrementer). This checks the first argument so - * we know if rtl_intercept wants us to check for - * a bottom half, signals and so on (normal return) or - * we're returning from a real-time interrupt or have - * interrupts soft disabled so we cannot enter Linux. - * -- Cort - */ - .globl ret_from_int -ret_from_int: - cmpi 0,r3,0 - beq 10f - /* we're allowed to do signal/bh checks */ - b ret_from_syscall #ifdef __SMP__ .globl ret_from_smpfork ret_from_smpfork: bl schedule_tail + b ret_from_except #endif - .globl ret_from_syscall -ret_from_syscall: + .globl ret_from_intercept +ret_from_intercept: + /* + * We may be returning from RTL and cannot do the normal checks + * -- Cort + */ + cmpi 0,r3,0 + beq 10f .globl ret_from_except ret_from_except: -0: mfmsr r30 /* Disable interrupts */ - rlwinm r30,r30,0,17,15 /* clear MSR_EE */ - SYNC /* Some chip revs need this... */ - mtmsr r30 - SYNC +0: /* disable interrupts */ + lis r30,int_control@h + ori r30,r30,int_control@l + lwz r30,0(r30) + mtlr r30 + blrl + lwz r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f @@ -317,9 +309,13 @@ lost_irq_ret: bl do_bottom_half .globl do_bottom_half_ret do_bottom_half_ret: -2: SYNC - mtmsr r30 /* disable interrupts again */ - SYNC +2: /* disable interrupts */ + lis r30,int_control@h + ori r30,r30,int_control@l + lwz r30,0(r30) + mtlr r30 + blrl + lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR beq+ 10f /* if so, check need_resched and signals */ diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c index 3d6feed13..fb80dc493 100644 --- a/arch/ppc/kernel/gemini_pci.c +++ b/arch/ppc/kernel/gemini_pci.c @@ -229,13 +229,11 @@ __init void layout_bus( struct pci_bus *bus ) { struct pci_dev *dev; - if (!bus->devices && !bus->children) - return; - io_base = ALIGN(io_base, 4*KB); mem_base = ALIGN(mem_base, 4*KB); - for( dev = bus->devices; dev; dev = dev->sibling ) { + pci_for_each_dev(dev) + { if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) || ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER)) layout_dev( dev ); diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c index fadddda8b..d7ca91780 100644 --- a/arch/ppc/kernel/gemini_setup.c +++ b/arch/ppc/kernel/gemini_setup.c @@ -330,7 +330,7 @@ void __init gemini_init_IRQ(void) int i; /* gemini has no 8259 */ - open_pic.irq_offset = 0; + open_pic_irq_offset = 0; for( i=0; i < NR_IRQS; i++ ) irq_desc[i].handler = &open_pic; openpic_init(1); @@ -515,7 +515,7 @@ void gemini_post_irq(int irq) * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ - if ( irq >= open_pic.irq_offset) + if ( irq >= open_pic_irq_offset) openpic_eoi( smp_processor_id() ); } diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 451a1cad4..a70ba8bfd 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -287,7 +287,8 @@ turn_on_mmu: stw r2,GPR2(r21); \ stw r1,0(r21); \ tovirt(r1,r21); /* set new kernel sp */ \ - SAVE_4GPRS(3, r21); + SAVE_4GPRS(3, r21); \ + SAVE_GPR(7, r21); /* * Note: code which follows this uses cr0.eq (set if from kernel), * r21, r22 (SRR0), and r23 (SRR1). @@ -374,7 +375,7 @@ HardwareInterrupt: .globl do_IRQ_intercept do_IRQ_intercept: .long do_IRQ; - .long ret_from_except + .long ret_from_intercept #else bl apus_interrupt_entry #endif /* CONFIG_APUS */ @@ -424,7 +425,7 @@ Decrementer: .globl timer_interrupt_intercept timer_interrupt_intercept: .long timer_interrupt - .long ret_from_except + .long ret_from_intercept STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -674,7 +675,6 @@ DataStoreTLBMiss: transfer_to_handler: stw r22,_NIP(r21) stw r23,_MSR(r21) - SAVE_GPR(7, r21) SAVE_4GPRS(8, r21) SAVE_8GPRS(12, r21) SAVE_8GPRS(24, r21) diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S index abc651218..ba3284ad8 100644 --- a/arch/ppc/kernel/head_4xx.S +++ b/arch/ppc/kernel/head_4xx.S @@ -27,10 +27,8 @@ #include <linux/config.h> #include <asm/processor.h> -#include <asm/4xx.h> -#include <asm/403gcx.h> -#include <asm/405gp.h> #include <asm/page.h> +#include <asm/pgtable.h> #include <asm/mmu.h> #include "ppc_asm.h" @@ -58,7 +56,7 @@ ### execution begins here, the following registers contain valid, yet ### optional, information: ### -### r3 - ??? +### r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) ### r4 - Starting address of the init RAM disk ### r5 - Ending address of the init RAM disk ### r6 - Start of kernel command line string (e.g. "mem=96m") @@ -80,17 +78,55 @@ _GLOBAL(_start) li r24,0 - ## Establish exception vector base + ## We should still be executing code at physical address 0x0000xxxx + ## at this point. However, start_here is at virtual address + ## 0xC000xxxx. So, set up a TLB mapping to cover this once + ## translation is enabled. + + lis r3,KERNELBASE@h # Load the kernel virtual address + addis r3,r3,KERNELBASE@l + tophys(r4,r3) # Load the kernel physical address + + ## Save the existing PID and load the kernel PID. + + mfspr r7,SPRN_PID # Save the old PID + li r0,0 + mtspr SPRN_PID,r0 # Load the kernel PID + + ## Configure and load entry into TLB slot 0. - lis r0,KERNELBASE@h - mtspr SPRN_EVPR,r0 + clrrwi r4,r4,10 # Mask off the real page number - ## Jump to the main PowerPC kernel start-up code + ## XXX - Temporarily set the TLB_I bit because of cache issues that + ## seem to foul-up the exception handling code. + + ori r4,r4,(TLB_WR | TLB_EX | TLB_I) # Set the write and execute bits -1: lis r7,start_here@ha - addi r7,r7,start_here@l - mtlr r7 - blr + clrrwi r3,r3,10 # Mask off the effective page number + ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) + + tlbwe r4,r0,TLB_DATA # Load the data portion of the entry + tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry + isync + + mtspr SPRN_PID,r7 # Restore the existing PID + + ## Establish the exception vector base + + lis r4,KERNELBASE@h # EVPR only uses the high 16-bits + tophys(r0,r4) # Use the physical address + mtspr SPRN_EVPR,r0 + + ## Enable the MMU and jump to the main PowerPC kernel start-up code + + mfmsr r0 # Get the machine state register + ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation + mtspr SPRN_SRR1,r0 # Set up the new machine state register + lis r0,start_here@h + ori r0,r0,start_here@l + mtspr SPRN_SRR0,r0 # Set up the new instruction pointer + rfi # Jump to start_here w/ translation on + ### ### Exception vector entry code. This code runs with address translation @@ -129,7 +165,8 @@ _GLOBAL(_start) stw r2,GPR2(r21); /* Save r2 on the stack */\ stw r1,0(r21); \ tovirt(r1,r21); /* Set-up new kernel stack pointer */\ - SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */ + SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */\ + SAVE_GPR(7, r21); /* Save r7 on the stack */ ## Common exception code for standard (non-critical) exceptions. @@ -166,7 +203,7 @@ label: START_EXCEPTION(n, label); \ STND_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,STND_EXC; \ + li r7,STND_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) @@ -175,23 +212,10 @@ label: START_EXCEPTION(n, label); \ CRIT_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,CRIT_EXC; \ + li r7,CRIT_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) - -#define INTR_EXCEPTION(n, label, func) \ - START_EXCEPTION(n, label); \ - STND_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,STND_EXC; \ - li r20,MSR_KERNEL; \ - li r4,0; \ - bl transfer_to_handler; \ -_GLOBAL(do_IRQ_intercept); \ - .long func; \ - .long ret_from_except - ### ### Exception vectors. @@ -214,7 +238,7 @@ _GLOBAL(do_IRQ_intercept); \ mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2 stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR) @@ -226,15 +250,24 @@ _GLOBAL(do_IRQ_intercept); \ mr r4,r22 # Pass SRR0 as arg2 mr r5,r23 # Pass SRR1 as arg3 addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1) ### 0x0500 - External Interrupt Exception - INTR_EXCEPTION(0x0500, HardwareInterrupt, do_IRQ) - + START_EXCEPTION(0x0500, HardwareInterrupt) + STND_EXCEPTION_PROLOG + addi r3,r1,STACK_FRAME_OVERHEAD + li r7,STND_EXC + li r20,MSR_KERNEL + li r4,0 + bl transfer_to_handler +_GLOBAL(do_IRQ_intercept) + .long do_IRQ + .long ret_from_intercept + ### 0x0600 - Alignment Exception START_EXCEPTION(0x0600, Alignment) @@ -242,7 +275,7 @@ _GLOBAL(do_IRQ_intercept); \ mfspr r4,SPRN_DEAR # Grab the DEAR and save it stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(AlignmentException) @@ -252,7 +285,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x0700, ProgramCheck) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(ProgramCheckException) @@ -266,7 +299,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x0C00, SystemCall) STND_EXCEPTION_PROLOG stw r3,ORIG_GPR3(r21) - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(DoSyscall) @@ -275,11 +308,21 @@ _GLOBAL(do_IRQ_intercept); \ STND_EXCEPTION(0x0E00, Trap_0E, UnknownException) STND_EXCEPTION(0x0F00, Trap_0F, UnknownException) -#if 0 ### 0x1000 - Programmable Interval Timer (PIT) Exception - STND_EXCEPTION(0x1000, PITException, UnknownException) + START_EXCEPTION(0x1000, Decrementer) + STND_EXCEPTION_PROLOG + lis r0,TSR_PIS@h # Set-up the PIT exception mask + mtspr SPRN_TSR,r0 # Clear the PIT exception + addi r3,r1,STACK_FRAME_OVERHEAD + li r7,STND_EXC # This is a standard exception + li r20,MSR_KERNEL + bl transfer_to_handler +_GLOBAL(timer_interrupt_intercept) + .long timer_interrupt + .long ret_from_intercept +#if 0 ### 0x1010 - Fixed Interval Timer (FIT) Exception STND_EXCEPTION(0x1010, FITException, UnknownException) @@ -294,7 +337,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x1100, DTLBMiss) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC + li r7,STND_EXC li r20,MSR_KERNEL FINISH_EXCEPTION(UnknownException) @@ -303,7 +346,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x1200, ITLBMiss) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC + li r7,STND_EXC li r20,MSR_KERNEL FINISH_EXCEPTION(UnknownException) @@ -341,7 +384,6 @@ _GLOBAL(do_IRQ_intercept); \ _GLOBAL(transfer_to_handler) stw r22,_NIP(r21) # Save the faulting IP on the stack stw r23,_MSR(r21) # Save the exception MSR on the stack - SAVE_GPR(7, r21) # Save r7 on the stack SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack @@ -367,7 +409,7 @@ _GLOBAL(transfer_to_handler) bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE lwz r24,0(r23) # Virtual address of the handler lwz r23,4(r23) # Handler return pointer - cmpwi cr0,r0,STND_EXC # What type of exception is this? + cmpwi cr0,r7,STND_EXC # What type of exception is this? bne 3f # It is a critical exception... ## Standard exception jump path @@ -432,67 +474,10 @@ _GLOBAL(giveup_fpu) _GLOBAL(abort) mfspr r13,SPRN_DBCR - ori r13,r13,DBCR_RST(SYSTEM)@h + oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h mtspr SPRN_DBCR,r13 - -### -### This code is jumped-to from the startup code. It copies the kernel -### image from wherever it happens to be currently running at in physical -### address space to physical address 0. -### -### In general, for a running Linux/PPC system: -### Kernel Physical Address (KPA) = 0x00000000 -### Kernel Virtual Address (KVA) = 0xC0000000 -### - -#if 0 -relocate_kernel: - lis r9,0x426f /* if booted from BootX, don't */ - addi r9,r9,0x6f58 /* translate source addr */ - cmpw r31,r9 /* (we have to on chrp) */ - beq 7f - rlwinm r4,r4,0,8,31 /* translate source address */ - add r4,r4,r3 /* to region mapped with BATs */ -7: addis r9,r26,klimit@ha /* fetch klimit */ - lwz r25,klimit@l(r9) - addis r25,r25,-KERNELBASE@h - li r6,0 /* Destination offset */ - li r5,0x4000 /* # bytes of memory to copy */ - bl copy_and_flush /* copy the first 0x4000 bytes */ - addi r0,r3,4f@l /* jump to the address of 4f */ - mtctr r0 /* in copy and do the rest. */ - bctr /* jump to the copy */ -4: mr r5,r25 - bl copy_and_flush /* copy the rest */ - b turn_on_mmu -/* - * Copy routine used to copy the kernel to start at physical address 0 - * and flush and invalidate the caches as needed. - * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset - * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. - */ -copy_and_flush: - addi r5,r5,-4 - addi r6,r6,-4 -4: li r0,8 - mtctr r0 -3: addi r6,r6,4 /* copy a cache line */ - lwzx r0,r6,r4 - stwx r0,r6,r3 - bdnz 3b - dcbst r6,r3 /* write it to memory */ - sync - icbi r6,r3 /* flush the icache line */ - cmplw 0,r6,r5 - blt 4b - isync - addi r5,r5,4 - addi r6,r6,4 - blr -#endif - ### ### This is where the main kernel code starts. ### diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index c5a55c6a2..94cd67d3b 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -197,7 +197,8 @@ turn_on_mmu: stw r2,GPR2(r21); \ stw r1,0(r21); \ tovirt(r1,r21); /* set new kernel sp */ \ - SAVE_4GPRS(3, r21); + SAVE_4GPRS(3, r21); \ + SAVE_GPR(7, r21); /* * Note: code which follows this uses cr0.eq (set if from kernel), * r21, r22 (SRR0), and r23 (SRR1). @@ -265,34 +266,6 @@ InstructionAccess: . = 0x500; HardwareInterrupt: EXCEPTION_PROLOG; -#ifdef CONFIG_APUS - /* This is horrible, but there's no way around it. Enable the - data cache so the IRQ hardware register can be accessed - without cache intervention. Then disable interrupts and get - the current emulated m68k IPL value. */ - - mfmsr 20 - xori r20,r20,MSR_DR - sync - mtmsr r20 - sync - - lis r3,APUS_IPL_EMU@h - - li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT) - stb r20,APUS_IPL_EMU@l(r3) - eieio - - lbz r3,APUS_IPL_EMU@l(r3) - - mfmsr r20 - xori r20,r20,MSR_DR - sync - mtmsr r20 - sync - - stw r3,(_CCR+4)(r21); -#endif addi r3,r1,STACK_FRAME_OVERHEAD li r20,MSR_KERNEL li r4,0 @@ -300,7 +273,7 @@ HardwareInterrupt: .globl do_IRQ_intercept do_IRQ_intercept: .long do_IRQ; - .long ret_from_except + .long ret_from_intercept /* Alignment exception */ @@ -342,7 +315,7 @@ Decrementer: .globl timer_interrupt_intercept timer_interrupt_intercept: .long timer_interrupt - .long ret_from_except + .long ret_from_intercept STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -591,7 +564,6 @@ transfer_to_handler: lis r22,MSR_POW@h andc r23,r23,r22 stw r23,_MSR(r21) - SAVE_GPR(7, r21) SAVE_4GPRS(8, r21) SAVE_8GPRS(12, r21) SAVE_8GPRS(24, r21) diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index a09d6ad98..c2f2d1c11 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -294,11 +294,10 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) } } -asmlinkage void do_IRQ(struct pt_regs *regs, int isfake) +asmlinkage int do_IRQ(struct pt_regs *regs, int isfake) { int cpu = smp_processor_id(); int irq; - hardirq_enter( cpu ); /* every arch is required to have a get_irq -- Cort */ @@ -320,10 +319,9 @@ asmlinkage void do_IRQ(struct pt_regs *regs, int isfake) out: hardirq_exit( cpu ); + return 1; /* lets ret_from_int know we can do checks */ } - - unsigned long probe_irq_on (void) { return 0; diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c index a9c9137a0..ad2c224bb 100644 --- a/arch/ppc/kernel/oak_setup.c +++ b/arch/ppc/kernel/oak_setup.c @@ -7,26 +7,74 @@ * Description: * Architecture- / platform-specific boot-time initialization code for * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek - * <dmalek@jlc.net>. + * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek + * <dan@net4x.com>. * */ #include <linux/config.h> #include <linux/init.h> +#include <linux/smp.h> +#include <linux/threads.h> +#include <linux/interrupt.h> +#include <linux/param.h> #include <linux/string.h> +#include <asm/processor.h> +#include <asm/board.h> #include <asm/machdep.h> #include <asm/page.h> +#include "local_irq.h" +#include "ppc4xx_pic.h" +#include "time.h" #include "oak_setup.h" +/* Function Prototypes */ +extern void abort(void); + +/* Global Variables */ + +unsigned char __res[sizeof(bd_t)]; + + +/* + * void __init oak_init() + * + * Description: + * This routine... + * + * Input(s): + * r3 - Optional pointer to a board information structure. + * r4 - Optional pointer to the physical starting address of the init RAM + * disk. + * r5 - Optional pointer to the physical ending address of the init RAM + * disk. + * r6 - Optional pointer to the physical starting address of any kernel + * command-line parameters. + * r7 - Optional pointer to the physical ending address of any kernel + * command-line parameters. + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ void __init oak_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { -#if 0 + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) { + memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); + } + #if defined(CONFIG_BLK_DEV_INITRD) /* * If the init RAM disk has been configured in, and there's a valid @@ -44,24 +92,25 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5, *(char *)(r7 + KERNELBASE) = 0; strcpy(cmd_line, (char *)(r6 + KERNELBASE)); } -#endif /* 0 */ + + /* Initialize machine-dependency vectors */ ppc_md.setup_arch = oak_setup_arch; - ppc_md.setup_residual = NULL; + ppc_md.setup_residual = oak_setup_residual; ppc_md.get_cpuinfo = NULL; ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = NULL; - ppc_md.get_irq = NULL; + ppc_md.init_IRQ = oak_init_IRQ; + ppc_md.get_irq = oak_get_irq; ppc_md.init = NULL; - ppc_md.restart = NULL; - ppc_md.power_off = NULL; - ppc_md.halt = NULL; + ppc_md.restart = oak_restart; + ppc_md.power_off = oak_power_off; + ppc_md.halt = oak_halt; - ppc_md.time_init = NULL; - ppc_md.set_rtc_time = NULL; - ppc_md.get_rtc_time = NULL; - ppc_md.calibrate_decr = NULL; + ppc_md.time_init = oak_time_init; + ppc_md.set_rtc_time = oak_set_rtc_time; + ppc_md.get_rtc_time = oak_get_rtc_time; + ppc_md.calibrate_decr = oak_calibrate_decr; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -77,8 +126,168 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5, return; } +/* + * Document me. + */ void __init oak_setup_arch(void) { + /* XXX - Implement me */ +} + +/* + * int oak_setup_residual() + * + * Description: + * This routine pretty-prints the platform's internal CPU and bus clock + * frequencies into the buffer for usage in /proc/cpuinfo. + * + * Input(s): + * *buffer - Buffer into which CPU and bus clock frequencies are to be + * printed. + * + * Output(s): + * *buffer - Buffer with the CPU and bus clock frequencies. + * + * Returns: + * The number of bytes copied into 'buffer' if OK, otherwise zero or less + * on error. + */ +int +oak_setup_residual(char *buffer) +{ + int len = 0; + bd_t *bp = (bd_t *)__res; + + len += sprintf(len + buffer, + "clock\t\t: %dMHz\n" + "bus clock\t\t: %dMHz\n", + bp->bi_intfreq / 1000000, + bp->bi_busfreq / 1000000); + + return (len); +} + +/* + * Document me. + */ +void __init +oak_init_IRQ(void) +{ + int i; + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].handler = ppc4xx_pic; + } + + return; +} + +/* + * Document me. + */ +int +oak_get_irq(struct pt_regs *regs) +{ + return (ppc4xx_pic_get_irq(regs)); +} + +/* + * Document me. + */ +void +oak_restart(char *cmd) +{ + abort(); +} + +/* + * Document me. + */ +void +oak_power_off(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +void +oak_halt(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +void __init +oak_time_init(void) +{ + /* XXX - Implement me */ +} + +/* + * Document me. + */ +int __init +oak_set_rtc_time(unsigned long time) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * Document me. + */ +unsigned long __init +oak_get_rtc_time(void) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * void __init oak_calibrate_decr() + * + * Description: + * This routine retrieves the internal processor frequency from the board + * information structure, sets up the kernel timer decrementer based on + * that value, enables the 403 programmable interval timer (PIT) and sets + * it up for auto-reload. + * + * Input(s): + * N/A + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +void __init +oak_calibrate_decr(void) +{ + unsigned int freq; + bd_t *bip = (bd_t *)__res; + + freq = bip->bi_intfreq; + + decrementer_count = freq / HZ; + count_period_num = 1; + count_period_den = freq; + + /* Enable the PIT and set auto-reload of its value */ + + mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); } diff --git a/arch/ppc/kernel/oak_setup.h b/arch/ppc/kernel/oak_setup.h index 10f7d7354..62cfac906 100644 --- a/arch/ppc/kernel/oak_setup.h +++ b/arch/ppc/kernel/oak_setup.h @@ -15,14 +15,32 @@ #ifndef __OAK_SETUP_H__ #define __OAK_SETUP_H__ +#include <asm/ptrace.h> +#include <asm/board.h> + + #ifdef __cplusplus extern "C" { #endif -extern void oak_init(unsigned long r3, - unsigned long ird_start, unsigned long ird_end, - unsigned long cline_start, unsigned long cline_end); -extern void oak_setup_arch(void); +extern unsigned char __res[sizeof(bd_t)]; + +extern void oak_init(unsigned long r3, + unsigned long ird_start, + unsigned long ird_end, + unsigned long cline_start, + unsigned long cline_end); +extern void oak_setup_arch(void); +extern int oak_setup_residual(char *buffer); +extern void oak_init_IRQ(void); +extern int oak_get_irq(struct pt_regs *regs); +extern void oak_restart(char *cmd); +extern void oak_power_off(void); +extern void oak_halt(void); +extern void oak_time_init(void); +extern int oak_set_rtc_time(unsigned long now); +extern unsigned long oak_get_rtc_time(void); +extern void oak_calibrate_decr(void); #ifdef __cplusplus diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 02e276729..6857aa36f 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -38,6 +38,7 @@ struct hw_interrupt_type open_pic = { 0, 0 }; +int open_pic_irq_offset; /* * Accesses to the current processor's registers @@ -69,7 +70,7 @@ struct hw_interrupt_type open_pic = { * -- Cort */ #define check_arg_irq(irq) \ - /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \ + /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \ printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/ #define check_arg_cpu(cpu) \ if (cpu < 0 || cpu >= NumProcessors) \ @@ -212,11 +213,11 @@ void __init openpic_init(int main_pic) /* Initialize external interrupts */ if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc); /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, open_pic.irq_offset, 1, 1); + openpic_initirq(0, 8, open_pic_irq_offset, 1, 1); openpic_mapirq(0, 1<<0); for (i = 1; i < NumSources; i++) { /* Enabled, Priority 8 */ - openpic_initirq(i, 8, open_pic.irq_offset+i, 0, + openpic_initirq(i, 8, open_pic_irq_offset+i, 0, i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); /* Processor 0 */ openpic_mapirq(i, 1<<0); @@ -416,13 +417,13 @@ void openpic_maptimer(u_int timer, u_int cpumask) void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } void openpic_disable_irq(u_int irq) { check_arg_irq(irq); - openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } /* diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h index 2673263cf..3e51ffba3 100644 --- a/arch/ppc/kernel/open_pic.h +++ b/arch/ppc/kernel/open_pic.h @@ -7,4 +7,5 @@ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); void openpic_enable_IPI(u_int ipi); void do_openpic_setup_cpu(void); +extern int open_pic_irq_offset; #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index ec1ff3565..6c98bbf2c 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -9,6 +9,7 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/openpic.h> +#include <linux/errno.h> #include <asm/processor.h> #include <asm/io.h> @@ -21,7 +22,7 @@ #include "pci.h" -static void __init pcibios_claim_resources(struct pci_bus *); +static void __init pcibios_claim_resources(struct list_head *); unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -69,10 +70,9 @@ struct pci_ops generic_pci_ops = void __init pcibios_init(void) { printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = ~0L; pci_scan_bus(0, &generic_pci_ops, NULL); - pcibios_claim_resources(pci_root); - if ( ppc_md.pcibios_fixup ) + pcibios_claim_resources(&pci_root_buses); + if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); } @@ -162,3 +162,75 @@ void __init pcibios_align_resource(void *data, struct resource *res, unsigned long size) { } + +int pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * Assign new address to PCI resource. We hope our resource information + * is complete. We don't re-assign resources unless we are + * forced to do so. + * + * Expects start=0, end=size-1, flags=resource type. + */ + +int pci_assign_resource(struct pci_dev *dev, int i) +{ + struct resource *r = &dev->resource[i]; + struct resource *pr = pci_find_parent_resource(dev, r); + unsigned long size = r->end + 1; + u32 new, check; + + if (!pr) { + printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) { + if (allocate_resource(pr, r, size, 0x100, ~0, size, NULL, NULL)) { + printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); + return -EBUSY; + } + } else { + if (allocate_resource(pr, r, size, 0x10000, ~0, size, NULL, NULL)) { + printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); + return -EBUSY; + } + } + if (i < 6) { + int reg = PCI_BASE_ADDRESS_0 + 4*i; + new = r->start | (r->flags & PCI_REGION_FLAG_MASK); + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if (new != check) + printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check); + } else if (i == PCI_ROM_RESOURCE) { + r->flags |= PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK)); + } + printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i); + return 0; +} diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c index 99bfa4f8b..ea3338aef 100644 --- a/arch/ppc/kernel/pmac_nvram.c +++ b/arch/ppc/kernel/pmac_nvram.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <asm/system.h> #include <asm/prom.h> +#include <asm/machdep.h> #include <linux/adb.h> #include <linux/pmu.h> diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c index 60b497cd6..3b7dd283f 100644 --- a/arch/ppc/kernel/pmac_time.c +++ b/arch/ppc/kernel/pmac_time.c @@ -24,6 +24,7 @@ #include <asm/system.h> #include <asm/io.h> #include <asm/pgtable.h> +#include <asm/machdep.h> #include "time.h" diff --git a/arch/ppc/kernel/ppc4xx_pic.c b/arch/ppc/kernel/ppc4xx_pic.c new file mode 100644 index 000000000..8b40080b4 --- /dev/null +++ b/arch/ppc/kernel/ppc4xx_pic.c @@ -0,0 +1,204 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: ppc4xx_pic.c + * + * Description: + * Interrupt controller driver for PowerPC 4xx-based processors. + */ + +/* + * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has + * 32 possible interrupts, a majority of which are not implemented on + * all cores. There are six configurable, external interrupt pins and + * there are eight internal interrupts for the on-chip serial port + * (SPU), DMA controller, and JTAG controller. + * + * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32 + * possible interrupts as well. There are seven, configurable external + * interrupt pins and there are 17 internal interrupts for the on-chip + * serial port, DMA controller, on-chip Ethernet controller, PCI, etc. + * + */ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/stddef.h> + +#include <asm/processor.h> +#include <asm/system.h> +#include <asm/irq.h> + +#include "local_irq.h" +#include "ppc4xx_pic.h" + + +/* Global Variables */ + +struct hw_interrupt_type *ppc4xx_pic; + + +/* Function Prototypes */ + +static void ppc403_aic_enable(unsigned int irq); +static void ppc403_aic_disable(unsigned int irq); +static void ppc403_aic_disable_and_ack(unsigned int irq); + +static void ppc405_uic_enable(unsigned int irq); +static void ppc405_uic_disable(unsigned int irq); +static void ppc405_uic_disable_and_ack(unsigned int irq); + +static struct hw_interrupt_type ppc403_aic = { + "403GC AIC", + NULL, + NULL, + ppc403_aic_enable, + ppc403_aic_disable, + ppc403_aic_disable_and_ack, + 0 +}; + +static struct hw_interrupt_type ppc405_uic = { + "405GP UIC", + NULL, + NULL, + ppc405_uic_enable, + ppc405_uic_disable, + ppc405_uic_disable_and_ack, + 0 +}; + +/* + * Document me. + */ +void __init +ppc4xx_pic_init(void) +{ + unsigned long ver = PVR_VER(mfspr(SPRN_PVR)); + + switch (ver) { + + case PVR_VER(PVR_403GC): + /* + * Disable all external interrupts until they are + * explicity requested. + */ + ppc_cached_irq_mask[0] = 0; + mtdcr(DCRN_EXIER, 0); + + ppc4xx_pic = &ppc403_aic; + break; + + case PVR_VER(PVR_405GP): + ppc4xx_pic = &ppc405_uic; + break; + } + + return; +} + +/* + * XXX - Currently 403-specific! + * + * Document me. + */ +int +ppc4xx_pic_get_irq(struct pt_regs *regs) +{ + int irq; + unsigned long bits, mask = (1 << 31); + + /* + * Only report the status of those interrupts that are actually + * enabled. + */ + + bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); + + /* + * Walk through the interrupts from highest priority to lowest, and + * report the first pending interrupt found. + */ + + for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) { + if (bits & mask) + break; + } + + return (irq); +} + +/* + * Document me. + */ +static void +ppc403_aic_enable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] |= (1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +/* + * Document me. + */ +static void +ppc403_aic_disable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +/* + * Document me. + */ +static void +ppc403_aic_disable_and_ack(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); + mtdcr(DCRN_EXISR, (1 << (31 - bit))); +} + +/* + * Document me. + */ +static void +ppc405_uic_enable(unsigned int irq) +{ + /* XXX - Implement me. */ +} + +/* + * Document me. + */ +static void +ppc405_uic_disable(unsigned int irq) +{ + /* XXX - Implement me. */ +} + +/* + * Document me. + */ +static void +ppc405_uic_disable_and_ack(unsigned int irq) +{ + /* XXX - Implement me. */ +} diff --git a/arch/ppc/kernel/ppc4xx_pic.h b/arch/ppc/kernel/ppc4xx_pic.h new file mode 100644 index 000000000..6de862a46 --- /dev/null +++ b/arch/ppc/kernel/ppc4xx_pic.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: ppc4xx_pic.h + * + * Description: + * Interrupt controller driver for PowerPC 4xx-based processors. + */ + +#ifndef __PPC4XX_PIC_H__ +#define __PPC4XX_PIC_H__ + +#include <asm/ptrace.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +/* External Global Variables */ + +extern struct hw_interrupt_type *ppc4xx_pic; + + +/* Function Prototypes */ + +extern void ppc4xx_pic_init(void); +extern int ppc4xx_pic_get_irq(struct pt_regs *regs); + + +#ifdef __cplusplus +} +#endif + +#endif /* __PPC4XX_PIC_H__ */ diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 397685d43..65e925034 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -260,10 +260,8 @@ EXPORT_SYMBOL(screen_info); #endif EXPORT_SYMBOL(int_control); -#if !defined(CONFIG_4xx) EXPORT_SYMBOL(timer_interrupt_intercept); EXPORT_SYMBOL(timer_interrupt); -#endif extern unsigned long do_IRQ_intercept; EXPORT_SYMBOL(do_IRQ_intercept); EXPORT_SYMBOL(irq_desc); @@ -272,3 +270,4 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(decrementer_count); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); +EXPORT_SYMBOL(do_bottom_half); diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 64b171042..241b7c33c 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -287,11 +287,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { + unsigned long msr; struct pt_regs * childregs, *kregs; #ifdef __SMP__ extern void ret_from_smpfork(void); #else - extern void ret_from_syscall(void); + extern void ret_from_except(void); #endif /* Copy registers */ childregs = ((struct pt_regs *) @@ -308,9 +309,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef __SMP__ kregs->nip = (unsigned long)ret_from_smpfork; #else - kregs->nip = (unsigned long)ret_from_syscall; + kregs->nip = (unsigned long)ret_from_except; #endif - kregs->msr = MSR_KERNEL; + asm volatile("mfmsr %0" : "=r" (msr):); + kregs->msr = msr; kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD; kregs->gpr[2] = (unsigned long)p; diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index caffdcf99..dccb066ff 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -29,8 +29,9 @@ #endif #include <asm/bootx.h> #include <asm/machdep.h> - +#ifdef CONFIG_OAK #include "oak_setup.h" +#endif /* CONFIG_OAK */ extern void pmac_init(unsigned long r3, unsigned long r4, @@ -71,7 +72,13 @@ extern void gemini_init(unsigned long r3, extern boot_infos_t *boot_infos; char saved_command_line[256]; unsigned char aux_device_present; -struct int_control_struct int_control; +struct int_control_struct int_control = +{ + __no_use_cli, + __no_use_sti, + __no_use_restore_flags, + __no_use_save_flags +}; struct ide_machdep_calls ppc_ide_md; int parse_bootinfo(void); @@ -89,20 +96,13 @@ unsigned long SYSRQ_KEY; struct machdep_calls ppc_md; -/* copy of the residual data */ -#ifndef CONFIG_8xx -extern unsigned char __res[sizeof(RESIDUAL)]; -#else -extern unsigned char __res[sizeof(bd_t)]; -#endif - /* * Perhaps we can put the pmac screen_info[] here * on pmac as well so we don't need the ifdef's. * Until we get multiple-console support in here * that is. -- Cort */ -#ifndef CONFIG_8xx +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ 0, /* unused */ @@ -126,7 +126,7 @@ void __init pmac_find_display(void) { } -#else /* CONFIG_8xx */ +#else /* CONFIG_4xx || CONFIG_8xx */ /* We need this to satisfy some external references until we can * strip the kernel down. @@ -142,7 +142,7 @@ struct screen_info screen_info = { 0, /* orig-video-isVGA */ 16 /* orig-video-points */ }; -#endif /* CONFIG_8xx */ +#endif /* !CONFIG_4xx && !CONFIG_8xx */ void machine_restart(char *cmd) { @@ -193,6 +193,7 @@ int get_cpuinfo(char *buffer) unsigned long len = 0; unsigned long bogosum = 0; unsigned long i; + unsigned int pvr; unsigned short maj, min; #ifdef __SMP__ @@ -215,45 +216,75 @@ int get_cpuinfo(char *buffer) len += sprintf(len+buffer,"processor\t: %lu\n",i); len += sprintf(len+buffer,"cpu\t\t: "); - switch (GET_PVR >> 16) + pvr = GET_PVR; + + switch (PVR_VER(pvr)) { - case 1: + case 0x0001: len += sprintf(len+buffer, "601\n"); break; - case 3: + case 0x0003: len += sprintf(len+buffer, "603\n"); break; - case 4: + case 0x0004: len += sprintf(len+buffer, "604\n"); break; - case 6: + case 0x0006: len += sprintf(len+buffer, "603e\n"); break; - case 7: - len += sprintf(len+buffer, "603ev\n"); + case 0x0007: + len += sprintf(len+buffer, "603"); + if (((pvr >> 12) & 0xF) == 1) { + pvr ^= 0x00001000; /* revision fix-up */ + len += sprintf(len+buffer, "r\n"); + } else { + len += sprintf(len+buffer, "ev\n"); + } break; - case 8: - len += sprintf(len+buffer, "750\n"); + case 0x0008: /* 740/750(P) */ + case 0x1008: + len += sprintf(len+buffer, "750%s\n", + PVR_VER(pvr) == 0x1008 ? "P" : ""); len += sprintf(len+buffer, "temperature \t: %lu C\n", cpu_temp()); break; - case 9: - len += sprintf(len+buffer, "604e\n"); + case 0x0009: /* 604e/604r */ + case 0x000A: + len += sprintf(len+buffer, "604"); + + if (PVR_VER(pvr) == 0x000A || + ((pvr >> 12) & 0xF) != 0) { + pvr &= ~0x00003000; /* revision fix-up */ + len += sprintf(len+buffer, "r\n"); + } else { + len += sprintf(len+buffer, "e\n"); + } break; - case 10: - len += sprintf(len+buffer, "604ev5 (MachV)\n"); + case 0x000C: + len += sprintf(len+buffer, "7400\n"); break; - case 12: - len += sprintf(len+buffer, "7400 (G4)\n"); + case 0x0020: + len += sprintf(len+buffer, "403G"); + switch ((pvr >> 8) & 0xFF) { + case 0x02: + len += sprintf(len+buffer, "C\n"); + break; + case 0x14: + len += sprintf(len+buffer, "CX\n"); + break; + } break; - case 50: + case 0x0050: len += sprintf(len+buffer, "821\n"); - case 80: - len += sprintf(len+buffer, "860\n"); + break; + case 0x0081: + len += sprintf(len+buffer, "8240\n"); + break; + case 0x4011: + len += sprintf(len+buffer, "405GP\n"); break; default: - len += sprintf(len+buffer, "unknown (%lx)\n", - GET_PVR>>16); + len += sprintf(len+buffer, "unknown (%08x)\n", pvr); break; } @@ -292,6 +323,22 @@ int get_cpuinfo(char *buffer) len += ppc_md.setup_residual(buffer + len); } + switch (PVR_VER(pvr)) + { + case 0x0020: + maj = PVR_MAJ(pvr) + 1; + min = PVR_MIN(pvr); + break; + case 0x1008: + maj = ((pvr >> 8) & 0xFF) - 1; + min = pvr & 0xFF; + break; + default: + maj = (pvr >> 8) & 0xFF; + min = pvr & 0xFF; + break; + } + len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min); len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n", @@ -362,11 +409,6 @@ unsigned long __init identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - int_control.int_sti = __no_use_sti; - int_control.int_cli = __no_use_cli; - int_control.int_save_flags = __no_use_save_flags; - int_control.int_restore_flags = __no_use_restore_flags; - parse_bootinfo(); if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); @@ -674,25 +716,25 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->word72 = __le16_to_cpu(id->word72); id->word73 = __le16_to_cpu(id->word73); id->word74 = __le16_to_cpu(id->word74); - id->word75 = __le16_to_cpu(id->word75); + id->queue_depth = __le16_to_cpu(id->queue_depth); id->word76 = __le16_to_cpu(id->word76); id->word77 = __le16_to_cpu(id->word77); id->word78 = __le16_to_cpu(id->word78); id->word79 = __le16_to_cpu(id->word79); - id->word80 = __le16_to_cpu(id->word80); - id->word81 = __le16_to_cpu(id->word81); - id->command_sets = __le16_to_cpu(id->command_sets); - id->word83 = __le16_to_cpu(id->word83); - id->word84 = __le16_to_cpu(id->word84); - id->word85 = __le16_to_cpu(id->word85); - id->word86 = __le16_to_cpu(id->word86); - id->word87 = __le16_to_cpu(id->word87); + id->major_rev_num = __le16_to_cpu(id->major_rev_num); + id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); + id->command_set_1 = __le16_to_cpu(id->command_set_1); + id->command_set_2 = __le16_to_cpu(id->command_set_2); + id->cfsse = __le16_to_cpu(id->cfsse); + id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); + id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); + id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); id->word89 = __le16_to_cpu(id->word89); id->word90 = __le16_to_cpu(id->word90); - id->word91 = __le16_to_cpu(id->word91); + id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); id->word92 = __le16_to_cpu(id->word92); - id->word93 = __le16_to_cpu(id->word93); + id->hw_config = __le16_to_cpu(id->hw_config); id->word94 = __le16_to_cpu(id->word94); id->word95 = __le16_to_cpu(id->word95); id->word96 = __le16_to_cpu(id->word96); @@ -727,7 +769,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->word125 = __le16_to_cpu(id->word125); id->word126 = __le16_to_cpu(id->word126); id->word127 = __le16_to_cpu(id->word127); - id->security = __le16_to_cpu(id->security); for (i=0; i<127; i++) id->reserved[i] = __le16_to_cpu(id->reserved[i]); } diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index c2891e21f..386764ddd 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -446,6 +446,8 @@ void __init smp_callin(void) */ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) ) do_openpic_setup_cpu(); + if ( _machine == _MACH_gemini ) + gemini_init_l2(); while(!smp_commenced) barrier(); __sti(); diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index e21c30e14..b695da797 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -68,7 +68,7 @@ unsigned count_period_den; /* count_period_num / count_period_den us */ * with interrupts disabled. * We set it up to overflow again in 1/HZ seconds. */ -void timer_interrupt(struct pt_regs * regs) +int timer_interrupt(struct pt_regs * regs) { int dval, d; unsigned long cpu = smp_processor_id(); @@ -141,6 +141,7 @@ void timer_interrupt(struct pt_regs * regs) ppc_md.heartbeat(); hardirq_exit(cpu); + return 1; /* lets ret_from_int know we can do checks */ } /* diff --git a/arch/ppc/kernel/time.h b/arch/ppc/kernel/time.h index a0a5c62d2..05d791546 100644 --- a/arch/ppc/kernel/time.h +++ b/arch/ppc/kernel/time.h @@ -6,8 +6,11 @@ * Paul Mackerras' version and mine for PReP and Pmac. */ +#include <linux/config.h> #include <linux/mc146818rtc.h> +#include <asm/processor.h> + /* time.c */ extern unsigned decrementer_count; extern unsigned count_period_num; @@ -22,13 +25,18 @@ int via_calibrate_decr(void); /* Accessor functions for the decrementer register. */ static __inline__ unsigned int get_dec(void) { - unsigned int ret; - - asm volatile("mfspr %0,22" : "=r" (ret) :); - return ret; +#if defined(CONFIG_4xx) + return (mfspr(SPRN_PIT)); +#else + return (mfspr(SPRN_DEC)); +#endif } static __inline__ void set_dec(unsigned int val) { - asm volatile("mtspr 22,%0" : : "r" (val)); +#if defined(CONFIG_4xx) + mtspr(SPRN_PIT, val); +#else + mtspr(SPRN_DEC, val); +#endif } diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 47fef50d4..04b4e2d36 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -194,7 +194,6 @@ void ProgramCheckException(struct pt_regs *regs) { #if defined(CONFIG_4xx) - unsigned int instr; unsigned int esr = mfspr(SPRN_ESR); if (esr & ESR_PTR) { |