From: Albert H. <he...@us...> - 2009-10-25 18:45:45
|
Update of /cvsroot/gc-linux/linux/arch/powerpc/kernel In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29988/arch/powerpc/kernel Modified Files: cputable.c head_32.S udbg.c Added Files: dma.c Log Message: Forward to v.2.6.30. Index: udbg.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/kernel/udbg.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** udbg.c 25 Oct 2009 18:33:46 -0000 1.5 --- udbg.c 25 Oct 2009 18:45:35 -0000 1.6 *************** *** 19,22 **** --- 19,23 ---- void (*udbg_putc)(char c); + void (*udbg_flush)(void); int (*udbg_getc)(void); int (*udbg_getc_poll)(void); *************** *** 77,80 **** --- 78,84 ---- udbg_putc(c); } + + if (udbg_flush) + udbg_flush(); } #if 0 *************** *** 99,102 **** --- 103,109 ---- } + if (udbg_flush) + udbg_flush(); + return n - remain; } --- NEW FILE: dma.c --- /* * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation * * Provide default implementations of the DMA mapping callbacks for * directly mapped busses. */ #include <linux/device.h> #include <linux/dma-mapping.h> #include <asm/bug.h> #include <asm/abs_addr.h> /* * Generic direct DMA implementation * * This implementation supports a per-device offset that can be applied if * the address at which memory is visible to devices is not 0. Platform code * can set archdata.dma_data to an unsigned long holding the offset. By * default the offset is PCI_DRAM_OFFSET. */ static unsigned long get_dma_direct_offset(struct device *dev) { if (dev) return (unsigned long)dev->archdata.dma_data; return PCI_DRAM_OFFSET; } void *dma_direct_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { void *ret; #ifdef CONFIG_NOT_COHERENT_CACHE ret = __dma_alloc_coherent(dev, size, dma_handle, flag); if (ret == NULL) return NULL; *dma_handle += get_dma_direct_offset(dev); return ret; #else struct page *page; int node = dev_to_node(dev); /* ignore region specifiers */ flag &= ~(__GFP_HIGHMEM); page = alloc_pages_node(node, flag, get_order(size)); if (page == NULL) return NULL; ret = page_address(page); memset(ret, 0, size); *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); return ret; #endif } void dma_direct_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { #ifdef CONFIG_NOT_COHERENT_CACHE __dma_free_coherent(size, vaddr); #else free_pages((unsigned long)vaddr, get_order(size)); #endif } static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction, struct dma_attrs *attrs) { struct scatterlist *sg; int i; for_each_sg(sgl, sg, nents, i) { sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); sg->dma_length = sg->length; __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); } return nents; } static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction, struct dma_attrs *attrs) { } static int dma_direct_dma_supported(struct device *dev, u64 mask) { #ifdef CONFIG_PPC64 /* Could be improved to check for memory though it better be * done via some global so platforms can set the limit in case * they have limited DMA windows */ return mask >= DMA_BIT_MASK(32); #else return 1; #endif } static inline dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { BUG_ON(dir == DMA_NONE); __dma_sync_page(page, offset, size, dir); return page_to_phys(page) + offset + get_dma_direct_offset(dev); } static inline void dma_direct_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { } #ifdef CONFIG_NOT_COHERENT_CACHE static inline void dma_direct_sync_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction) { struct scatterlist *sg; int i; for_each_sg(sgl, sg, nents, i) __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); } static inline void dma_direct_sync_single_range(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) { __dma_sync(bus_to_virt(dma_handle+offset), size, direction); } #endif struct dma_mapping_ops dma_direct_ops = { .alloc_coherent = dma_direct_alloc_coherent, .free_coherent = dma_direct_free_coherent, .map_sg = dma_direct_map_sg, .unmap_sg = dma_direct_unmap_sg, .dma_supported = dma_direct_dma_supported, .map_page = dma_direct_map_page, .unmap_page = dma_direct_unmap_page, #ifdef CONFIG_NOT_COHERENT_CACHE .sync_single_range_for_cpu = dma_direct_sync_single_range, .sync_single_range_for_device = dma_direct_sync_single_range, .sync_sg_for_cpu = dma_direct_sync_sg, .sync_sg_for_device = dma_direct_sync_sg, #endif }; EXPORT_SYMBOL(dma_direct_ops); Index: head_32.S =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/kernel/head_32.S,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** head_32.S 25 Oct 2009 18:33:46 -0000 1.9 --- head_32.S 25 Oct 2009 18:45:35 -0000 1.10 *************** *** 22,25 **** --- 22,26 ---- */ + #include <linux/init.h> #include <asm/reg.h> #include <asm/page.h> *************** *** 51,55 **** 1: ! .section .text.head, "ax" .stabs "arch/powerpc/kernel/",N_SO,0,0,0f .stabs "head_32.S",N_SO,0,0,0f --- 52,56 ---- 1: ! __HEAD .stabs "arch/powerpc/kernel/",N_SO,0,0,0f .stabs "head_32.S",N_SO,0,0,0f *************** *** 109,116 **** * (particularly on CHRP). */ - #ifdef CONFIG_PPC_MULTIPLATFORM cmpwi 0,r5,0 beq 1f /* find out where we are now */ bcl 20,31,$+4 --- 110,117 ---- * (particularly on CHRP). */ cmpwi 0,r5,0 beq 1f + #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE /* find out where we are now */ bcl 20,31,$+4 *************** *** 119,124 **** addi r8,r8,(_stext - 0b)@l /* current runtime base addr */ bl prom_init trap - #endif /* --- 120,128 ---- addi r8,r8,(_stext - 0b)@l /* current runtime base addr */ bl prom_init + #endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */ + + /* We never return. We also hit that trap if trying to boot + * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */ trap /* *************** *** 473,482 **** InstructionTLBMiss: /* ! * r0: stored ctr * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ - mfctr r0 /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_IMISS --- 477,485 ---- InstructionTLBMiss: /* ! * r0: scratch * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_IMISS *************** *** 497,522 **** beq- InstructionAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r3,0(r2) /* get linux-style pte */ ! andc. r1,r1,r3 /* check access & ~permission */ bne- InstructionAddressInvalid /* return if access not permitted */ ! ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r3,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ ! rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ and r1,r1,r2 /* writable if _RW and _DIRTY */ ! rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ ! rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ ! andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 - mfspr r3,SPRN_IMISS tlbli r3 mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ --- 500,524 ---- beq- InstructionAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r0,0(r2) /* get linux-style pte */ ! andc. r1,r1,r0 /* check access & ~permission */ bne- InstructionAddressInvalid /* return if access not permitted */ ! ori r0,r0,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r0,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwinm r1,r0,32-10,31,31 /* _PAGE_RW -> PP lsb */ ! rlwinm r2,r0,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ and r1,r1,r2 /* writable if _RW and _DIRTY */ ! rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ ! rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ ! andc r1,r0,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 tlbli r3 mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ *************** *** 529,533 **** addis r1,r1,0x2000 mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */ - mtctr r0 /* Restore CTR */ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ or r2,r2,r1 --- 531,534 ---- *************** *** 550,559 **** DataLoadTLBMiss: /* ! * r0: stored ctr * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ - mfctr r0 /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS --- 551,559 ---- DataLoadTLBMiss: /* ! * r0: scratch * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS *************** *** 574,602 **** beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r3,0(r2) /* get linux-style pte */ ! andc. r1,r1,r3 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ ! ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r3,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ ! rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ and r1,r1,r2 /* writable if _RW and _DIRTY */ ! rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ ! rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ ! andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 ! mfspr r3,SPRN_DMISS tlbld r3 - mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ - mtcrf 0x80,r3 rfi DataAddressInvalid: --- 574,613 ---- beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r0,0(r2) /* get linux-style pte */ ! andc. r1,r1,r0 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ ! ori r0,r0,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r0,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwinm r1,r0,32-10,31,31 /* _PAGE_RW -> PP lsb */ ! rlwinm r2,r0,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ and r1,r1,r2 /* writable if _RW and _DIRTY */ ! rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ ! rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ ! andc r1,r0,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 ! mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ ! mtcrf 0x80,r2 ! BEGIN_MMU_FTR_SECTION ! li r0,1 ! mfspr r1,SPRN_SPRG4 ! rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ ! slw r0,r0,r2 ! xor r1,r0,r1 ! srw r0,r1,r2 ! mtspr SPRN_SPRG4,r1 ! mfspr r2,SPRN_SRR1 ! rlwimi r2,r0,31-14,14,14 ! mtspr SPRN_SRR1,r2 ! END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) tlbld r3 rfi DataAddressInvalid: *************** *** 605,609 **** addis r1,r1,0x2000 mtspr SPRN_DSISR,r1 - mtctr r0 /* Restore CTR */ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ mtspr SPRN_SRR1,r2 --- 616,619 ---- *************** *** 625,634 **** DataStoreTLBMiss: /* ! * r0: stored ctr * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ - mfctr r0 /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS --- 635,643 ---- DataStoreTLBMiss: /* ! * r0: scratch * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte * r3: scratch */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS *************** *** 649,673 **** beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r3,0(r2) /* get linux-style pte */ ! andc. r1,r1,r3 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ ! ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r3,0(r2) /* update PTE (accessed/dirty bits) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ li r1,0xe05 /* clear out reserved bits & PP lsb */ ! andc r1,r3,r1 /* PP = user? 2: 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 ! mfspr r3,SPRN_DMISS tlbld r3 - mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ - mtcrf 0x80,r3 rfi --- 658,693 ---- beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ ! lwz r0,0(r2) /* get linux-style pte */ ! andc. r1,r1,r0 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ ! ori r0,r0,_PAGE_ACCESSED|_PAGE_DIRTY /* * NOTE! We are assuming this is not an SMP system, otherwise * we would need to update the pte atomically with lwarx/stwcx. */ ! stw r0,0(r2) /* update PTE (accessed/dirty bits) */ /* Convert linux-style PTE to low word of PPC-style PTE */ ! rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ li r1,0xe05 /* clear out reserved bits & PP lsb */ ! andc r1,r0,r1 /* PP = user? 2: 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 ! mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ ! mtcrf 0x80,r2 ! BEGIN_MMU_FTR_SECTION ! li r0,1 ! mfspr r1,SPRN_SPRG4 ! rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ ! slw r0,r0,r2 ! xor r1,r0,r1 ! srw r0,r1,r2 ! mtspr SPRN_SPRG4,r1 ! mfspr r2,SPRN_SRR1 ! rlwimi r2,r0,31-14,14,14 ! mtspr SPRN_SRR1,r2 ! END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) tlbld r3 rfi Index: cputable.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/kernel/cputable.c,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** cputable.c 25 Oct 2009 18:33:46 -0000 1.8 --- cputable.c 25 Oct 2009 18:45:35 -0000 1.9 *************** *** 36,39 **** --- 36,43 ---- */ #ifdef CONFIG_PPC32 + extern void __setup_cpu_e200(unsigned long offset, struct cpu_spec* spec); + extern void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec* spec); + extern void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec* spec); + extern void __setup_cpu_e500mc(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec); *************** *** 44,47 **** --- 48,52 ---- extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); + extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec); extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); *************** *** 378,382 **** .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_cpu_type = "ppc64/compat-power5+", .platform = "power5+", }, --- 383,388 ---- .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_cpu_type = "ppc64/ibm-compat-v1", ! .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", }, *************** *** 412,416 **** .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_cpu_type = "ppc64/compat-power6", .platform = "power6", }, --- 418,423 ---- .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_cpu_type = "ppc64/ibm-compat-v1", ! .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power6", }, *************** *** 425,429 **** .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_cpu_type = "ppc64/compat-power7", .platform = "power7", }, --- 432,437 ---- .dcache_bsize = 128, .machine_check = machine_check_generic, ! .oprofile_type = PPC_OPROFILE_POWER4, ! .oprofile_cpu_type = "ppc64/ibm-compat-v1", .platform = "power7", }, *************** *** 727,730 **** --- 735,740 ---- .machine_check = machine_check_generic, .platform = "ppc750", + .oprofile_cpu_type = "ppc/750", + .oprofile_type = PPC_OPROFILE_G4, }, { /* 750FX rev 2.0 must disable HID0[DPM] */ *************** *** 742,745 **** --- 752,757 ---- .machine_check = machine_check_generic, .platform = "ppc750", + .oprofile_cpu_type = "ppc/750", + .oprofile_type = PPC_OPROFILE_G4, }, { /* 750FX (All revs except 2.0) */ *************** *** 757,760 **** --- 769,774 ---- .machine_check = machine_check_generic, .platform = "ppc750", + .oprofile_cpu_type = "ppc/750", + .oprofile_type = PPC_OPROFILE_G4, }, { /* 750GX */ *************** *** 772,775 **** --- 786,791 ---- .machine_check = machine_check_generic, .platform = "ppc750", + .oprofile_cpu_type = "ppc/750", + .oprofile_type = PPC_OPROFILE_G4, }, { /* 740/750 (L2CR bit need fixup for 740) */ *************** *** 1078,1082 **** .cpu_features = CPU_FTRS_E300C2, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, ! .mmu_features = MMU_FTR_USE_HIGH_BATS, .icache_bsize = 32, .dcache_bsize = 32, --- 1094,1099 ---- .cpu_features = CPU_FTRS_E300C2, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, ! .mmu_features = MMU_FTR_USE_HIGH_BATS | ! MMU_FTR_NEED_DTLB_SW_LRU, .icache_bsize = 32, .dcache_bsize = 32, *************** *** 1091,1095 **** .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_USER, ! .mmu_features = MMU_FTR_USE_HIGH_BATS, .icache_bsize = 32, .dcache_bsize = 32, --- 1108,1113 ---- .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_USER, ! .mmu_features = MMU_FTR_USE_HIGH_BATS | ! MMU_FTR_NEED_DTLB_SW_LRU, .icache_bsize = 32, .dcache_bsize = 32, *************** *** 1106,1110 **** .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_USER, ! .mmu_features = MMU_FTR_USE_HIGH_BATS, .icache_bsize = 32, .dcache_bsize = 32, --- 1124,1129 ---- .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_USER, ! .mmu_features = MMU_FTR_USE_HIGH_BATS | ! MMU_FTR_NEED_DTLB_SW_LRU, .icache_bsize = 32, .dcache_bsize = 32, *************** *** 1635,1638 **** --- 1654,1670 ---- .platform = "ppc440", }, + { /* 460SX */ + .pvr_mask = 0xffffff00, + .pvr_value = 0x13541800, + .cpu_name = "460SX", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE, + .mmu_features = MMU_FTR_TYPE_44x, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_460sx, + .machine_check = machine_check_440A, + .platform = "ppc440", + }, { /* default match */ .pvr_mask = 0x00000000, *************** *** 1688,1691 **** --- 1720,1724 ---- .mmu_features = MMU_FTR_TYPE_FSL_E, .dcache_bsize = 32, + .cpu_setup = __setup_cpu_e200, .machine_check = machine_check_e200, .platform = "ppc5554", *************** *** 1707,1710 **** --- 1740,1744 ---- .oprofile_cpu_type = "ppc/e500", .oprofile_type = PPC_OPROFILE_FSL_EMB, + .cpu_setup = __setup_cpu_e500v1, .machine_check = machine_check_e500, .platform = "ppc8540", *************** *** 1725,1728 **** --- 1759,1763 ---- .oprofile_cpu_type = "ppc/e500", .oprofile_type = PPC_OPROFILE_FSL_EMB, + .cpu_setup = __setup_cpu_e500v2, .machine_check = machine_check_e500, .platform = "ppc8548", *************** *** 1734,1738 **** .cpu_features = CPU_FTRS_E500MC, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, ! .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS, .icache_bsize = 64, .dcache_bsize = 64, --- 1769,1774 ---- .cpu_features = CPU_FTRS_E500MC, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, ! .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | ! MMU_FTR_USE_TLBILX, .icache_bsize = 64, .dcache_bsize = 64, *************** *** 1740,1743 **** --- 1776,1780 ---- .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ .oprofile_type = PPC_OPROFILE_FSL_EMB, + .cpu_setup = __setup_cpu_e500mc, .machine_check = machine_check_e500, .platform = "ppce500mc", *************** *** 1763,1835 **** static struct cpu_spec the_cpu_spec; ! struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) { - struct cpu_spec *s = cpu_specs; struct cpu_spec *t = &the_cpu_spec; ! int i; - s = PTRRELOC(s); t = PTRRELOC(t); ! for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) ! if ((pvr & s->pvr_mask) == s->pvr_value) { ! /* ! * If we are overriding a previous value derived ! * from the real PVR with a new value obtained ! * using a logical PVR value, don't modify the ! * performance monitor fields. ! */ ! if (t->num_pmcs && !s->num_pmcs) { ! t->cpu_name = s->cpu_name; ! t->cpu_features = s->cpu_features; ! t->cpu_user_features = s->cpu_user_features; ! t->icache_bsize = s->icache_bsize; ! t->dcache_bsize = s->dcache_bsize; ! t->cpu_setup = s->cpu_setup; ! t->cpu_restore = s->cpu_restore; ! t->platform = s->platform; ! /* ! * If we have passed through this logic once ! * before and have pulled the default case ! * because the real PVR was not found inside ! * cpu_specs[], then we are possibly running in ! * compatibility mode. In that case, let the ! * oprofiler know which set of compatibility ! * counters to pull from by making sure the ! * oprofile_cpu_type string is set to that of ! * compatibility mode. If the oprofile_cpu_type ! * already has a value, then we are possibly ! * overriding a real PVR with a logical one, and, ! * in that case, keep the current value for ! * oprofile_cpu_type. ! */ ! if (t->oprofile_cpu_type == NULL) ! t->oprofile_cpu_type = s->oprofile_cpu_type; ! } else ! *t = *s; ! *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; ! /* ! * Set the base platform string once; assumes ! * we're called with real pvr first. ! */ ! if (*PTRRELOC(&powerpc_base_platform) == NULL) ! *PTRRELOC(&powerpc_base_platform) = t->platform; #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) ! /* ppc64 and booke expect identify_cpu to also call ! * setup_cpu for that processor. I will consolidate ! * that at a later time, for now, just use #ifdef. ! * we also don't need to PTRRELOC the function pointer ! * on ppc64 and booke as we are running at 0 in real ! * mode on ppc64 and reloc_offset is always 0 on booke. ! */ ! if (s->cpu_setup) { ! s->cpu_setup(offset, s); ! } #endif /* CONFIG_PPC64 || CONFIG_BOOKE */ return s; } BUG(); return NULL; } --- 1800,1884 ---- static struct cpu_spec the_cpu_spec; ! static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) { struct cpu_spec *t = &the_cpu_spec; ! struct cpu_spec old; t = PTRRELOC(t); + old = *t; ! /* Copy everything, then do fixups */ ! *t = *s; ! /* ! * If we are overriding a previous value derived from the real ! * PVR with a new value obtained using a logical PVR value, ! * don't modify the performance monitor fields. ! */ ! if (old.num_pmcs && !s->num_pmcs) { ! t->num_pmcs = old.num_pmcs; ! t->pmc_type = old.pmc_type; ! t->oprofile_type = old.oprofile_type; ! t->oprofile_mmcra_sihv = old.oprofile_mmcra_sihv; ! t->oprofile_mmcra_sipr = old.oprofile_mmcra_sipr; ! t->oprofile_mmcra_clear = old.oprofile_mmcra_clear; ! ! /* ! * If we have passed through this logic once before and ! * have pulled the default case because the real PVR was ! * not found inside cpu_specs[], then we are possibly ! * running in compatibility mode. In that case, let the ! * oprofiler know which set of compatibility counters to ! * pull from by making sure the oprofile_cpu_type string ! * is set to that of compatibility mode. If the ! * oprofile_cpu_type already has a value, then we are ! * possibly overriding a real PVR with a logical one, ! * and, in that case, keep the current value for ! * oprofile_cpu_type. ! */ ! if (old.oprofile_cpu_type != NULL) { ! t->oprofile_cpu_type = old.oprofile_cpu_type; ! t->oprofile_type = old.oprofile_type; ! } ! } ! ! *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; ! ! /* ! * Set the base platform string once; assumes ! * we're called with real pvr first. ! */ ! if (*PTRRELOC(&powerpc_base_platform) == NULL) ! *PTRRELOC(&powerpc_base_platform) = t->platform; #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) ! /* ppc64 and booke expect identify_cpu to also call setup_cpu for ! * that processor. I will consolidate that at a later time, for now, ! * just use #ifdef. We also don't need to PTRRELOC the function ! * pointer on ppc64 and booke as we are running at 0 in real mode ! * on ppc64 and reloc_offset is always 0 on booke. ! */ ! if (s->cpu_setup) { ! s->cpu_setup(offset, s); ! } #endif /* CONFIG_PPC64 || CONFIG_BOOKE */ + } + + struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) + { + struct cpu_spec *s = cpu_specs; + int i; + + s = PTRRELOC(s); + + for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) { + if ((pvr & s->pvr_mask) == s->pvr_value) { + setup_cpu_spec(offset, s); return s; } + } + BUG(); + return NULL; } |