Commit 8483ca3c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'merge' of master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc

* 'merge' of master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc:
  [POWERPC] Make sure __cpu_preinit_ppc970 gets called on 970GX processors
  [POWERPC] Fix CHRP platforms with only 8259
  [POWERPC] IPIC: Fix spinlock recursion in set_irq_handler
  [POWERPC] Fix the UCC rx/tx clock of QE
  [POWERPC] cell: update defconfig
  [POWERPC] spufs: fix another off-by-one bug in spufs_mbox_read
  [POWERPC] spufs: fix signal2 file to report signal2
  [POWERPC] Fix device_is_compatible() const warning
  [POWERPC] Cell timebase bug workaround
  [POWERPC] Support feature fixups in modules
  [POWERPC] Support feature fixups in vdso's
  [POWERPC] Support nested cpu feature sections
  [POWERPC] Consolidate feature fixup code
  [POWERPC] Fix hang in start_ldr if _end or _edata is unaligned
  [POWERPC] Fix spelling errors in ucc_fast.c and ucc_slow.c
  [POWERPC] Don't require execute perms on wrapper when building zImage.initrd
  [POWERPC] Add 970GX cputable entry
  [POWERPC] Fix build breakage with CONFIG_PPC32
  [POWERPC] Fix compiler warning message on get_property call
  [POWERPC] Simplify stolen time calculation
parents ede847c4 190a24f5
...@@ -115,7 +115,7 @@ endif ...@@ -115,7 +115,7 @@ endif
quiet_cmd_wrap = WRAP $@ quiet_cmd_wrap = WRAP $@
cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux
quiet_cmd_wrap_initrd = WRAP $@ quiet_cmd_wrap_initrd = WRAP $@
cmd_wrap_initrd =$(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
-i $(obj)/ramdisk.image.gz vmlinux -i $(obj)/ramdisk.image.gz vmlinux
$(obj)/zImage.chrp: vmlinux $(wrapperbits) $(obj)/zImage.chrp: vmlinux $(wrapperbits)
......
...@@ -254,6 +254,7 @@ CONFIG_SYN_COOKIES=y ...@@ -254,6 +254,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_TUNNEL=y CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set # CONFIG_TCP_CONG_ADVANCED is not set
...@@ -275,7 +276,9 @@ CONFIG_INET6_XFRM_TUNNEL=m ...@@ -275,7 +276,9 @@ CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_INET6_XFRM_MODE_BEET is not set
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
# CONFIG_IPV6_SIT is not set
CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set
...@@ -405,6 +408,12 @@ CONFIG_BLK_DEV_INITRD=y ...@@ -405,6 +408,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set # CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set # CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# #
# ATA/ATAPI/MFM/RLL support # ATA/ATAPI/MFM/RLL support
# #
...@@ -738,7 +747,6 @@ CONFIG_GEN_RTC=y ...@@ -738,7 +747,6 @@ CONFIG_GEN_RTC=y
# TPM devices # TPM devices
# #
# CONFIG_TCG_TPM is not set # CONFIG_TCG_TPM is not set
# CONFIG_TELCLOCK is not set
# #
# I2C support # I2C support
...@@ -802,6 +810,7 @@ CONFIG_I2C_ALGOBIT=y ...@@ -802,6 +810,7 @@ CONFIG_I2C_ALGOBIT=y
# #
# Dallas's 1-wire bus # Dallas's 1-wire bus
# #
# CONFIG_W1 is not set
# #
# Hardware Monitoring support # Hardware Monitoring support
...@@ -809,15 +818,10 @@ CONFIG_I2C_ALGOBIT=y ...@@ -809,15 +818,10 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set # CONFIG_HWMON_VID is not set
#
# Misc devices
#
# #
# Multimedia devices # Multimedia devices
# #
# CONFIG_VIDEO_DEV is not set # CONFIG_VIDEO_DEV is not set
CONFIG_VIDEO_V4L2=y
# #
# Digital Video Broadcasting Devices # Digital Video Broadcasting Devices
...@@ -923,6 +927,7 @@ CONFIG_EXT3_FS=y ...@@ -923,6 +927,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set # CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y CONFIG_FS_MBCACHE=y
...@@ -930,6 +935,7 @@ CONFIG_FS_MBCACHE=y ...@@ -930,6 +935,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set # CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set # CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set # CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set # CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set # CONFIG_ROMFS_FS is not set
...@@ -1129,6 +1135,7 @@ CONFIG_DEBUG_FS=y ...@@ -1129,6 +1135,7 @@ CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set # CONFIG_FORCED_INLINING is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_STACK_USAGE is not set
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/oprofile_impl.h> #include <asm/oprofile_impl.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/prom.h> /* for PTRRELOC on ARCH=ppc */
struct cpu_spec* cur_cpu_spec = NULL; struct cpu_spec* cur_cpu_spec = NULL;
EXPORT_SYMBOL(cur_cpu_spec); EXPORT_SYMBOL(cur_cpu_spec);
...@@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void); ...@@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void);
#define PPC_FEATURE_SPE_COMP 0 #define PPC_FEATURE_SPE_COMP 0
#endif #endif
struct cpu_spec cpu_specs[] = { static struct cpu_spec cpu_specs[] = {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
{ /* Power3 */ { /* Power3 */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -227,6 +228,21 @@ struct cpu_spec cpu_specs[] = { ...@@ -227,6 +228,21 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4, .oprofile_type = PPC_OPROFILE_POWER4,
.platform = "ppc970", .platform = "ppc970",
}, },
{ /* PPC970GX */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00450000,
.cpu_name = "PPC970GX",
.cpu_features = CPU_FTRS_PPC970,
.cpu_user_features = COMMON_USER_POWER4 |
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "ppc970",
},
{ /* Power5 GR */ { /* Power5 GR */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
.pvr_value = 0x003a0000, .pvr_value = 0x003a0000,
...@@ -1152,3 +1168,71 @@ struct cpu_spec cpu_specs[] = { ...@@ -1152,3 +1168,71 @@ struct cpu_spec cpu_specs[] = {
#endif /* !CLASSIC_PPC */ #endif /* !CLASSIC_PPC */
#endif /* CONFIG_PPC32 */ #endif /* CONFIG_PPC32 */
}; };
struct cpu_spec *identify_cpu(unsigned long offset)
{
struct cpu_spec *s = cpu_specs;
struct cpu_spec **cur = &cur_cpu_spec;
unsigned int pvr = mfspr(SPRN_PVR);
int i;
s = PTRRELOC(s);
cur = PTRRELOC(cur);
if (*cur != NULL)
return PTRRELOC(*cur);
for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
if ((pvr & s->pvr_mask) == s->pvr_value) {
*cur = cpu_specs + i;
#ifdef CONFIG_PPC64
/* ppc64 expects identify_cpu to also call setup_cpu
* for that processor. I will consolidate that at a
* later time, for now, just use our friend #ifdef.
* we also don't need to PTRRELOC the function pointer
* on ppc64 as we are running at 0 in real mode.
*/
if (s->cpu_setup) {
s->cpu_setup(offset, s);
}
#endif /* CONFIG_PPC64 */
return s;
}
BUG();
return NULL;
}
void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
{
struct fixup_entry {
unsigned long mask;
unsigned long value;
long start_off;
long end_off;
} *fcur, *fend;
fcur = fixup_start;
fend = fixup_end;
for (; fcur < fend; fcur++) {
unsigned int *pstart, *pend, *p;
if ((value & fcur->mask) == fcur->value)
continue;
/* These PTRRELOCs will disappear once the new scheme for
* modules and vdso is implemented
*/
pstart = ((unsigned int *)fcur) + (fcur->start_off / 4);
pend = ((unsigned int *)fcur) + (fcur->end_off / 4);
for (p = pstart; p < pend; p++) {
*p = 0x60000000u;
asm volatile ("dcbst 0, %0" : : "r" (p));
}
asm volatile ("sync" : : : "memory");
for (p = pstart; p < pend; p++)
asm volatile ("icbi 0,%0" : : "r" (p));
asm volatile ("sync; isync" : : : "memory");
}
}
...@@ -1580,11 +1580,6 @@ _STATIC(__start_initialization_iSeries) ...@@ -1580,11 +1580,6 @@ _STATIC(__start_initialization_iSeries)
li r0,0 li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1) stdu r0,-STACK_FRAME_OVERHEAD(r1)
LOAD_REG_IMMEDIATE(r3,cpu_specs)
LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
li r5,0
bl .identify_cpu
LOAD_REG_IMMEDIATE(r2,__toc_start) LOAD_REG_IMMEDIATE(r2,__toc_start)
addi r2,r2,0x4000 addi r2,r2,0x4000
addi r2,r2,0x4000 addi r2,r2,0x4000
...@@ -1646,6 +1641,8 @@ _GLOBAL(__start_initialization_multiplatform) ...@@ -1646,6 +1641,8 @@ _GLOBAL(__start_initialization_multiplatform)
cmpwi r0,0x3c /* 970FX */ cmpwi r0,0x3c /* 970FX */
beq 1f beq 1f
cmpwi r0,0x44 /* 970MP */ cmpwi r0,0x44 /* 970MP */
beq 1f
cmpwi r0,0x45 /* 970GX */
bne 2f bne 2f
1: bl .__cpu_preinit_ppc970 1: bl .__cpu_preinit_ppc970
2: 2:
...@@ -1964,13 +1961,6 @@ _STATIC(start_here_multiplatform) ...@@ -1964,13 +1961,6 @@ _STATIC(start_here_multiplatform)
addi r2,r2,0x4000 addi r2,r2,0x4000
add r2,r2,r26 add r2,r2,r26
LOAD_REG_IMMEDIATE(r3, cpu_specs)
add r3,r3,r26
LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
add r4,r4,r26
mr r5,r26
bl .identify_cpu
/* Do very early kernel initializations, including initial hash table, /* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */ * stab and slb setup before we turn on relocation. */
...@@ -2000,13 +1990,6 @@ _STATIC(start_here_common) ...@@ -2000,13 +1990,6 @@ _STATIC(start_here_common)
li r0,0 li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1) stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* Apply the CPUs-specific fixups (nop out sections not relevant
* to this CPU
*/
li r3,0
bl .do_cpu_ftr_fixups
bl .do_fw_ftr_fixups
/* ptr to current */ /* ptr to current */
LOAD_REG_IMMEDIATE(r4, init_task) LOAD_REG_IMMEDIATE(r4, init_task)
std r4,PACACURRENT(r13) std r4,PACACURRENT(r13)
......
...@@ -101,80 +101,6 @@ _GLOBAL(reloc_got2) ...@@ -101,80 +101,6 @@ _GLOBAL(reloc_got2)
mtlr r11 mtlr r11
blr blr
/*
* identify_cpu,
* called with r3 = data offset and r4 = CPU number
* doesn't change r3
*/
_GLOBAL(identify_cpu)
addis r8,r3,cpu_specs@ha
addi r8,r8,cpu_specs@l
mfpvr r7
1:
lwz r5,CPU_SPEC_PVR_MASK(r8)
and r5,r5,r7
lwz r6,CPU_SPEC_PVR_VALUE(r8)
cmplw 0,r6,r5
beq 1f
addi r8,r8,CPU_SPEC_ENTRY_SIZE
b 1b
1:
addis r6,r3,cur_cpu_spec@ha
addi r6,r6,cur_cpu_spec@l
sub r8,r8,r3
stw r8,0(r6)
blr
/*
* do_cpu_ftr_fixups - goes through the list of CPU feature fixups
* and writes nop's over sections of code that don't apply for this cpu.
* r3 = data offset (not changed)
*/
_GLOBAL(do_cpu_ftr_fixups)
/* Get CPU 0 features */
addis r6,r3,cur_cpu_spec@ha
addi r6,r6,cur_cpu_spec@l
lwz r4,0(r6)
add r4,r4,r3
lwz r4,CPU_SPEC_FEATURES(r4)
/* Get the fixup table */
addis r6,r3,__start___ftr_fixup@ha
addi r6,r6,__start___ftr_fixup@l
addis r7,r3,__stop___ftr_fixup@ha
addi r7,r7,__stop___ftr_fixup@l
/* Do the fixup */
1: cmplw 0,r6,r7
bgelr
addi r6,r6,16
lwz r8,-16(r6) /* mask */
and r8,r8,r4
lwz r9,-12(r6) /* value */
cmplw 0,r8,r9
beq 1b
lwz r8,-8(r6) /* section begin */
lwz r9,-4(r6) /* section end */
subf. r9,r8,r9
beq 1b
/* write nops over the section of code */
/* todo: if large section, add a branch at the start of it */
srwi r9,r9,2
mtctr r9
add r8,r8,r3
lis r0,0x60000000@h /* nop */
3: stw r0,0(r8)
andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
beq 2f
dcbst 0,r8 /* suboptimal, but simpler */
sync
icbi 0,r8
2: addi r8,r8,4
bdnz 3b
sync /* additional sync needed on g4 */
isync
b 1b
/* /*
* call_setup_cpu - call the setup_cpu function for this cpu * call_setup_cpu - call the setup_cpu function for this cpu
* r3 = data offset, r24 = cpu number * r3 = data offset, r24 = cpu number
......
...@@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache) ...@@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache)
isync isync
blr blr
/*
* identify_cpu and calls setup_cpu
* In: r3 = base of the cpu_specs array
* r4 = address of cur_cpu_spec
* r5 = relocation offset
*/
_GLOBAL(identify_cpu)
mfpvr r7
1:
lwz r8,CPU_SPEC_PVR_MASK(r3)
and r8,r8,r7
lwz r9,CPU_SPEC_PVR_VALUE(r3)
cmplw 0,r9,r8
beq 1f
addi r3,r3,CPU_SPEC_ENTRY_SIZE
b 1b
1:
sub r0,r3,r5
std r0,0(r4)
ld r4,CPU_SPEC_SETUP(r3)
cmpdi 0,r4,0
add r4,r4,r5
beqlr
ld r4,0(r4)
add r4,r4,r5
mtctr r4
/* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */
mr r4,r3
mr r3,r5
bctr
/*
* do_cpu_ftr_fixups - goes through the list of CPU feature fixups
* and writes nop's over sections of code that don't apply for this cpu.
* r3 = data offset (not changed)
*/
_GLOBAL(do_cpu_ftr_fixups)
/* Get CPU 0 features */
LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
sub r6,r6,r3
ld r4,0(r6)
sub r4,r4,r3
ld r4,CPU_SPEC_FEATURES(r4)
/* Get the fixup table */
LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
sub r6,r6,r3
LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
sub r7,r7,r3
/* Do the fixup */
1: cmpld r6,r7
bgelr
addi r6,r6,32
ld r8,-32(r6) /* mask */
and r8,r8,r4
ld r9,-24(r6) /* value */
cmpld r8,r9
beq 1b
ld r8,-16(r6) /* section begin */
ld r9,-8(r6) /* section end */
subf. r9,r8,r9
beq 1b
/* write nops over the section of code */
/* todo: if large section, add a branch at the start of it */
srwi r9,r9,2
mtctr r9
sub r8,r8,r3
lis r0,0x60000000@h /* nop */
3: stw r0,0(r8)
andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
beq 2f
dcbst 0,r8 /* suboptimal, but simpler */
sync
icbi 0,r8
2: addi r8,r8,4
bdnz 3b
sync /* additional sync needed on g4 */
isync
b 1b
/*
* do_fw_ftr_fixups - goes through the list of firmware feature fixups
* and writes nop's over sections of code that don't apply for this firmware.
* r3 = data offset (not changed)
*/
_GLOBAL(do_fw_ftr_fixups)
/* Get firmware features */
LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features)
sub r6,r6,r3
ld r4,0(r6)
/* Get the fixup table */
LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup)
sub r6,r6,r3
LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup)
sub r7,r7,r3
/* Do the fixup */
1: cmpld r6,r7
bgelr
addi r6,r6,32
ld r8,-32(r6) /* mask */
and r8,r8,r4
ld r9,-24(r6) /* value */
cmpld r8,r9
beq 1b
ld r8,-16(r6) /* section begin */
ld r9,-8(r6) /* section end */
subf. r9,r8,r9
beq 1b
/* write nops over the section of code */
/* todo: if large section, add a branch at the start of it */
srwi r9,r9,2
mtctr r9
sub r8,r8,r3
lis r0,0x60000000@h /* nop */
3: stw r0,0(r8)
BEGIN_FTR_SECTION
dcbst 0,r8 /* suboptimal, but simpler */
sync
icbi 0,r8
END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE)
addi r8,r8,4
bdnz 3b
sync /* additional sync needed on g4 */
isync
b 1b
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
/* /*
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/cache.h> #include <linux/cache.h>
#include "setup.h"
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
#else #else
...@@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, ...@@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
return 0; return 0;
} }
static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
const char *name)
{
char *secstrings;
unsigned int i;
secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
for (i = 1; i < hdr->e_shnum; i++)
if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
return &sechdrs[i];
return NULL;
}
int module_finalize(const Elf_Ehdr *hdr, int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, const Elf_Shdr *sechdrs,
struct module *me) struct module *me)
{ {
char *secstrings; const Elf_Shdr *sect;
unsigned int i;
me->arch.bug_table = NULL; me->arch.bug_table = NULL;
me->arch.num_bugs = 0; me->arch.num_bugs = 0;
/* Find the __bug_table section, if present */ /* Find the __bug_table section, if present */
secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; sect = find_section(hdr, sechdrs, "__bug_table");
for (i = 1; i < hdr->e_shnum; i++) { if (sect != NULL) {
if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) me->arch.bug_table = (void *) sect->sh_addr;
continue; me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
me->arch.bug_table = (void *) sechdrs[i].sh_addr;
me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
break;
} }
/* /*
* Strictly speaking this should have a spinlock to protect against * Strictly speaking this should have a spinlock to protect against
* traversals, but since we only traverse on BUG()s, a spinlock * traversals, but since we only traverse on BUG()s, a spinlock
* could potentially lead to deadlock and thus be counter-productive. * could potentially lead to deadlock and thus be counter-productive.
*/ */
list_add(&me->arch.bug_list, &module_bug_list); list_add(&me->arch.bug_list, &module_bug_list);
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
if (sect != NULL)
do_feature_fixups(cur_cpu_spec->cpu_features,
(void *)sect->sh_addr,
(void *)sect->sh_addr + sect->sh_size);
return 0; return 0;
} }
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/module.h> #include <asm/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/firmware.h>
#include "setup.h"
/* FIXME: We don't do .init separately. To do this, we'd need to have /* FIXME: We don't do .init separately. To do this, we'd need to have
a separate r2 value in the init and core section, and stub between a separate r2 value in the init and core section, and stub between
...@@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
| (value & 0x03fffffc); | (value & 0x03fffffc);
break; break;
case R_PPC64_REL64:
/* 64 bits relative (used by features fixups) */
*location = value - (unsigned long)location;
break;
default: default:
printk("%s: Unknown ADD relocation: %lu\n", printk("%s: Unknown ADD relocation: %lu\n",
me->name, me->name,
...@@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
LIST_HEAD(module_bug_list); LIST_HEAD(module_bug_list);
int module_finalize(const Elf_Ehdr *hdr, static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, struct module *me) const Elf_Shdr *sechdrs,
const char *name)
{ {
char *secstrings; char *secstrings;
unsigned int i; unsigned int i;
secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
for (i = 1; i < hdr->e_shnum; i++)
if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
return &sechdrs[i];
return NULL;
}
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, struct module *me)
{
const Elf_Shdr *sect;
me->arch.bug_table = NULL; me->arch.bug_table = NULL;
me->arch.num_bugs = 0; me->arch.num_bugs = 0;
/* Find the __bug_table section, if present */ /* Find the __bug_table section, if present */
secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; sect = find_section(hdr, sechdrs, "__bug_table");
for (i = 1; i < hdr->e_shnum; i++) { if (sect != NULL) {
if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) me->arch.bug_table = (void *) sect->sh_addr;
continue; me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
me->arch.bug_table = (void *) sechdrs[i].sh_addr;
me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
break;
} }
/* /*
...@@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr,
*/ */
list_add(&me->arch.bug_list, &module_bug_list); list_add(&me->arch.bug_list, &module_bug_list);
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
if (sect != NULL)
do_feature_fixups(cur_cpu_spec->cpu_features,
(void *)sect->sh_addr,
(void *)sect->sh_addr + sect->sh_size);
sect = find_section(hdr, sechdrs, "__fw_ftr_fixup");
if (sect != NULL)
do_feature_fixups(powerpc_firmware_features,
(void *)sect->sh_addr,
(void *)sect->sh_addr + sect->sh_size);
return 0; return 0;
} }
......
...@@ -1014,7 +1014,7 @@ EXPORT_SYMBOL(find_all_nodes); ...@@ -1014,7 +1014,7 @@ EXPORT_SYMBOL(find_all_nodes);
/** Checks if the given "compat" string matches one of the strings in /** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property * the device's "compatible" property
*/ */
int device_is_compatible(struct device_node *device, const char *compat) int device_is_compatible(const struct device_node *device, const char *compat)
{ {
const char* cp; const char* cp;
int cplen, l; int cplen, l;
...@@ -1491,7 +1491,8 @@ static int __init prom_reconfig_setup(void) ...@@ -1491,7 +1491,8 @@ static int __init prom_reconfig_setup(void)
__initcall(prom_reconfig_setup); __initcall(prom_reconfig_setup);
#endif #endif
struct property *of_find_property(struct device_node *np, const char *name, struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp) int *lenp)
{ {
struct property *pp; struct property *pp;
...@@ -1512,7 +1513,8 @@ struct property *of_find_property(struct device_node *np, const char *name, ...@@ -1512,7 +1513,8 @@ struct property *of_find_property(struct device_node *np, const char *name,
* Find a property with a given name for a given node * Find a property with a given name for a given node
* and return the value. * and return the value.
*/ */
const void *get_property(struct device_node *np, const char *name, int *lenp) const void *get_property(const struct device_node *np, const char *name,
int *lenp)
{ {
struct property *pp = of_find_property(np,name,lenp); struct property *pp = of_find_property(np,name,lenp);
return pp ? pp->value : NULL; return pp ? pp->value : NULL;
......
...@@ -91,6 +91,7 @@ int ucache_bsize; ...@@ -91,6 +91,7 @@ int ucache_bsize;
unsigned long __init early_init(unsigned long dt_ptr) unsigned long __init early_init(unsigned long dt_ptr)
{ {
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct cpu_spec *spec;
/* First zero the BSS -- use memset_io, some platforms don't have /* First zero the BSS -- use memset_io, some platforms don't have
* caches on yet */ * caches on yet */
...@@ -100,8 +101,11 @@ unsigned long __init early_init(unsigned long dt_ptr) ...@@ -100,8 +101,11 @@ unsigned long __init early_init(unsigned long dt_ptr)
* Identify the CPU type and fix up code sections * Identify the CPU type and fix up code sections
* that depend on which cpu we have. * that depend on which cpu we have.
*/ */
identify_cpu(offset, 0); spec = identify_cpu(offset);
do_cpu_ftr_fixups(offset);
do_feature_fixups(spec->cpu_features,
PTRRELOC(&__start___ftr_fixup),
PTRRELOC(&__stop___ftr_fixup));
return KERNELBASE + offset; return KERNELBASE + offset;
} }
......
...@@ -170,6 +170,9 @@ void __init setup_paca(int cpu) ...@@ -170,6 +170,9 @@ void __init setup_paca(int cpu)
void __init early_setup(unsigned long dt_ptr) void __init early_setup(unsigned long dt_ptr)
{ {
/* Identify CPU type */
identify_cpu(0);
/* Assume we're on cpu 0 for now. Don't write to the paca yet! */ /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
setup_paca(0); setup_paca(0);
...@@ -348,6 +351,14 @@ void __init setup_system(void) ...@@ -348,6 +351,14 @@ void __init setup_system(void)
{ {
DBG(" -> setup_system()\n"); DBG(" -> setup_system()\n");
/* Apply the CPUs-specific and firmware specific fixups to kernel
* text (nop out sections not relevant to this CPU or this firmware)
*/
do_feature_fixups(cur_cpu_spec->cpu_features,
&__start___ftr_fixup, &__stop___ftr_fixup);
do_feature_fixups(powerpc_firmware_features,
&__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
/* /*
* Unflatten the device-tree passed by prom_init or kexec * Unflatten the device-tree passed by prom_init or kexec
*/ */
......
...@@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs) ...@@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs)
*/ */
struct cpu_purr_data { struct cpu_purr_data {
int initialized; /* thread is running */ int initialized; /* thread is running */
u64 tb0; /* timebase at origin time */
u64 purr0; /* PURR at origin time */
u64 tb; /* last TB value read */ u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */ u64 purr; /* last PURR value read */
u64 stolen; /* stolen time so far */
spinlock_t lock; spinlock_t lock;
}; };
...@@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data) ...@@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data)
{ {
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
p->tb0 = mftb(); p->tb = mftb();
p->purr0 = mfspr(SPRN_PURR); p->purr = mfspr(SPRN_PURR);
p->tb = p->tb0;
p->purr = 0;
wmb(); wmb();
p->initialized = 1; p->initialized = 1;
} }
...@@ -258,37 +253,24 @@ void snapshot_timebases(void) ...@@ -258,37 +253,24 @@ void snapshot_timebases(void)
void calculate_steal_time(void) void calculate_steal_time(void)
{ {
u64 tb, purr, t0; u64 tb, purr;
s64 stolen; s64 stolen;
struct cpu_purr_data *p0, *pme, *phim; struct cpu_purr_data *pme;
int cpu;
if (!cpu_has_feature(CPU_FTR_PURR)) if (!cpu_has_feature(CPU_FTR_PURR))
return; return;
cpu = smp_processor_id(); pme = &per_cpu(cpu_purr_data, smp_processor_id());
pme = &per_cpu(cpu_purr_data, cpu);
if (!pme->initialized) if (!pme->initialized)
return; /* this can happen in early boot */ return; /* this can happen in early boot */
p0 = &per_cpu(cpu_purr_data, cpu & ~1); spin_lock(&pme->lock);
phim = &per_cpu(cpu_purr_data, cpu ^ 1);
spin_lock(&p0->lock);
tb = mftb(); tb = mftb();
purr = mfspr(SPRN_PURR) - pme->purr0; purr = mfspr(SPRN_PURR);
if (!phim->initialized || !cpu_online(cpu ^ 1)) { stolen = (tb - pme->tb) - (purr - pme->purr);
stolen = (tb - pme->tb) - (purr - pme->purr); if (stolen > 0)
} else {
t0 = pme->tb0;
if (phim->tb0 < t0)
t0 = phim->tb0;
stolen = phim->tb - t0 - phim->purr - purr - p0->stolen;
}
if (stolen > 0) {
account_steal_time(current, stolen); account_steal_time(current, stolen);
p0->stolen += stolen;
}
pme->tb = tb; pme->tb = tb;
pme->purr = purr; pme->purr = purr;
spin_unlock(&p0->lock); spin_unlock(&pme->lock);
} }
/* /*
...@@ -297,30 +279,17 @@ void calculate_steal_time(void) ...@@ -297,30 +279,17 @@ void calculate_steal_time(void)
*/ */
static void snapshot_purr(void) static void snapshot_purr(void)
{ {
int cpu; struct cpu_purr_data *pme;
u64 purr;
struct cpu_purr_data *p0, *pme, *phim;
unsigned long flags; unsigned long flags;
if (!cpu_has_feature(CPU_FTR_PURR)) if (!cpu_has_feature(CPU_FTR_PURR))
return; return;
cpu = smp_processor_id(); pme = &per_cpu(cpu_purr_data, smp_processor_id());
pme = &per_cpu(cpu_purr_data, cpu); spin_lock_irqsave(&pme->lock, flags);
p0 = &per_cpu(cpu_purr_data, cpu & ~1); pme->tb = mftb();
phim = &per_cpu(cpu_purr_data, cpu ^ 1); pme->purr = mfspr(SPRN_PURR);
spin_lock_irqsave(&p0->lock, flags);
pme->tb = pme->tb0 = mftb();
purr = mfspr(SPRN_PURR);
if (!phim->initialized) {
pme->purr = 0;
pme->purr0 = purr;
} else {
/* set p->purr and p->purr0 for no change in p0->stolen */
pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen;
pme->purr0 = purr - pme->purr;
}
pme->initialized = 1; pme->initialized = 1;
spin_unlock_irqrestore(&p0->lock, flags); spin_unlock_irqrestore(&pme->lock, flags);
} }
#endif /* CONFIG_PPC_SPLPAR */ #endif /* CONFIG_PPC_SPLPAR */
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include "setup.h"
#undef DEBUG #undef DEBUG
#ifdef DEBUG #ifdef DEBUG
...@@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, ...@@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32,
return 0; return 0;
} }
static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
struct lib64_elfinfo *v64)
{
void *start32;
unsigned long size32;
#ifdef CONFIG_PPC64
void *start64;
unsigned long size64;
start64 = find_section64(v64->hdr, "__ftr_fixup", &size64);
if (start64)
do_feature_fixups(cur_cpu_spec->cpu_features,
start64, start64 + size64);
start64 = find_section64(v64->hdr, "__fw_ftr_fixup", &size64);
if (start64)
do_feature_fixups(powerpc_firmware_features,
start64, start64 + size64);
#endif /* CONFIG_PPC64 */
start32 = find_section32(v32->hdr, "__ftr_fixup", &size32);
if (start32)
do_feature_fixups(cur_cpu_spec->cpu_features,
start32, start32 + size32);
#ifdef CONFIG_PPC64
start32 = find_section32(v32->hdr, "__fw_ftr_fixup", &size32);
if (start32)
do_feature_fixups(powerpc_firmware_features,
start32, start32 + size32);
#endif /* CONFIG_PPC64 */
return 0;
}
static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
struct lib64_elfinfo *v64) struct lib64_elfinfo *v64)
{ {
...@@ -634,6 +673,9 @@ static __init int vdso_setup(void) ...@@ -634,6 +673,9 @@ static __init int vdso_setup(void)
if (vdso_fixup_datapage(&v32, &v64)) if (vdso_fixup_datapage(&v32, &v64))
return -1; return -1;
if (vdso_fixup_features(&v32, &v64))
return -1;
if (vdso_fixup_alt_funcs(&v32, &v64)) if (vdso_fixup_alt_funcs(&v32, &v64))
return -1; return -1;
...@@ -714,6 +756,7 @@ void __init vdso_init(void) ...@@ -714,6 +756,7 @@ void __init vdso_init(void)
* Setup the syscall map in the vDOS * Setup the syscall map in the vDOS
*/ */
vdso_setup_syscall_map(); vdso_setup_syscall_map();
/* /*
* Initialize the vDSO images in memory, that is do necessary * Initialize the vDSO images in memory, that is do necessary
* fixups of vDSO symbols, locate trampolines, etc... * fixups of vDSO symbols, locate trampolines, etc...
......
...@@ -32,6 +32,18 @@ SECTIONS ...@@ -32,6 +32,18 @@ SECTIONS
PROVIDE (_etext = .); PROVIDE (_etext = .);
PROVIDE (etext = .); PROVIDE (etext = .);
. = ALIGN(8);
__ftr_fixup : {
*(__ftr_fixup)
}
#ifdef CONFIG_PPC64
. = ALIGN(8);
__fw_ftr_fixup : {
*(__fw_ftr_fixup)
}
#endif
/* Other stuff is appended to the text segment: */ /* Other stuff is appended to the text segment: */
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) } .rodata1 : { *(.rodata1) }
......
...@@ -229,8 +229,10 @@ V_FUNCTION_BEGIN(__do_get_xsec) ...@@ -229,8 +229,10 @@ V_FUNCTION_BEGIN(__do_get_xsec)
xor r0,r8,r8 /* create dependency */ xor r0,r8,r8 /* create dependency */
add r3,r3,r0 add r3,r3,r0
/* Get TB & offset it */ /* Get TB & offset it. We use the MFTB macro which will generate
mftb r7 * workaround code for Cell.
*/
MFTB(r7)
ld r9,CFG_TB_ORIG_STAMP(r3) ld r9,CFG_TB_ORIG_STAMP(r3)
subf r7,r9,r7 subf r7,r9,r7
......
...@@ -31,6 +31,16 @@ SECTIONS ...@@ -31,6 +31,16 @@ SECTIONS
PROVIDE (_etext = .); PROVIDE (_etext = .);
PROVIDE (etext = .); PROVIDE (etext = .);
. = ALIGN(8);
__ftr_fixup : {
*(__ftr_fixup)
}
. = ALIGN(8);
__fw_ftr_fixup : {
*(__fw_ftr_fixup)
}
/* Other stuff is appended to the text segment: */ /* Other stuff is appended to the text segment: */
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) } .rodata1 : { *(.rodata1) }
......
...@@ -76,7 +76,7 @@ static inline int mmcra_must_set_sample(void) ...@@ -76,7 +76,7 @@ static inline int mmcra_must_set_sample(void)
{ {
if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) || if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
__is_processor(PV_970) || __is_processor(PV_970FX) || __is_processor(PV_970) || __is_processor(PV_970FX) ||
__is_processor(PV_970MP)) __is_processor(PV_970MP) || __is_processor(PV_970GX))
return 1; return 1;
return 0; return 0;
......
...@@ -385,7 +385,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf, ...@@ -385,7 +385,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
udata = (void __user *)buf; udata = (void __user *)buf;
spu_acquire(ctx); spu_acquire(ctx);
for (count = 0; count <= len; count += 4, udata++) { for (count = 0; (count + 4) <= len; count += 4, udata++) {
int ret; int ret;
ret = ctx->ops->mbox_read(ctx, &mbox_data); ret = ctx->ops->mbox_read(ctx, &mbox_data);
if (ret == 0) if (ret == 0)
......
...@@ -147,7 +147,7 @@ static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) ...@@ -147,7 +147,7 @@ static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
static u32 spu_hw_signal2_read(struct spu_context *ctx) static u32 spu_hw_signal2_read(struct spu_context *ctx)
{ {
return in_be32(&ctx->spu->problem->signal_notify1); return in_be32(&ctx->spu->problem->signal_notify2);
} }
static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
......
...@@ -477,8 +477,10 @@ static void __init chrp_find_8259(void) ...@@ -477,8 +477,10 @@ static void __init chrp_find_8259(void)
" address, polling\n"); " address, polling\n");
i8259_init(pic, chrp_int_ack); i8259_init(pic, chrp_int_ack);
if (ppc_md.get_irq == NULL) if (ppc_md.get_irq == NULL) {
ppc_md.get_irq = i8259_irq; ppc_md.get_irq = i8259_irq;
irq_set_default_host(i8259_get_host());
}
if (chrp_mpic != NULL) { if (chrp_mpic != NULL) {
cascade_irq = irq_of_parse_and_map(pic, 0); cascade_irq = irq_of_parse_and_map(pic, 0);
if (cascade_irq == NO_IRQ) if (cascade_irq == NO_IRQ)
......
...@@ -694,6 +694,11 @@ void * __init iSeries_early_setup(void) ...@@ -694,6 +694,11 @@ void * __init iSeries_early_setup(void)
{ {
unsigned long phys_mem_size; unsigned long phys_mem_size;
/* Identify CPU type. This is done again by the common code later
* on but calling this function multiple times is fine.
*/
identify_cpu(0);
powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_ISERIES;
powerpc_firmware_features |= FW_FEATURE_LPAR; powerpc_firmware_features |= FW_FEATURE_LPAR;
......
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
.section .text .section .text
.align 5 .align 5
#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) #if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \
(defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))
/* This gets called by via-pmu.c late during the sleep process. /* This gets called by via-pmu.c late during the sleep process.
* The PMU was already send the sleep command and will shut us down * The PMU was already send the sleep command and will shut us down
......
...@@ -224,6 +224,11 @@ static struct irq_host_ops i8259_host_ops = { ...@@ -224,6 +224,11 @@ static struct irq_host_ops i8259_host_ops = {
.xlate = i8259_host_xlate, .xlate = i8259_host_xlate,
}; };
struct irq_host *i8259_get_host(void)
{
return i8259_host;
}
/** /**
* i8259_init - Initialize the legacy controller * i8259_init - Initialize the legacy controller
* @node: device node of the legacy PIC (can be NULL, but then, it will match * @node: device node of the legacy PIC (can be NULL, but then, it will match
......
...@@ -473,9 +473,9 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) ...@@ -473,9 +473,9 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
if (flow_type & IRQ_TYPE_LEVEL_LOW) { if (flow_type & IRQ_TYPE_LEVEL_LOW) {
desc->status |= IRQ_LEVEL; desc->status |= IRQ_LEVEL;
set_irq_handler(virq, handle_level_irq); desc->handle_irq = handle_level_irq;
} else { } else {
set_irq_handler(virq, handle_edge_irq); desc->handle_irq = handle_edge_irq;
} }
/* only EXT IRQ senses are programmable on ipic /* only EXT IRQ senses are programmable on ipic
......
...@@ -207,6 +207,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode) ...@@ -207,6 +207,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
case QE_CLK18: source = 8; break; case QE_CLK18: source = 8; break;
case QE_CLK7: source = 9; break; case QE_CLK7: source = 9; break;
case QE_CLK8: source = 10; break; case QE_CLK8: source = 10; break;
case QE_CLK16: source = 11; break;
default: source = -1; break; default: source = -1; break;
} }
break; break;
...@@ -222,6 +223,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode) ...@@ -222,6 +223,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
case QE_CLK22: source = 8; break; case QE_CLK22: source = 8; break;
case QE_CLK7: source = 9; break; case QE_CLK7: source = 9; break;
case QE_CLK8: source = 10; break; case QE_CLK8: source = 10; break;
case QE_CLK16: source = 11; break;
default: source = -1; break; default: source = -1; break;
} }
break; break;
......
...@@ -163,7 +163,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc ...@@ -163,7 +163,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* check if the UCC port number is in range. */ /* check if the UCC port number is in range. */
if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
uccf_err("ucc_fast_init: Illagal UCC number!"); uccf_err("ucc_fast_init: Illegal UCC number!");
return -EINVAL; return -EINVAL;
} }
......
...@@ -152,7 +152,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc ...@@ -152,7 +152,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* check if the UCC port number is in range. */ /* check if the UCC port number is in range. */
if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
uccs_err("ucc_slow_init: Illagal UCC number!"); uccs_err("ucc_slow_init: Illegal UCC number!");
return -EINVAL; return -EINVAL;
} }
......
...@@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void) ...@@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void)
tsi = of_find_node_by_type(NULL, "tsi-bridge"); tsi = of_find_node_by_type(NULL, "tsi-bridge");
if (tsi) { if (tsi) {
unsigned int size; unsigned int size;
void *prop = get_property(tsi, "reg", &size); const void *prop = get_property(tsi, "reg", &size);
tsi108_csr_base = of_translate_address(tsi, prop); tsi108_csr_base = of_translate_address(tsi, prop);
of_node_put(tsi); of_node_put(tsi);
}; };
...@@ -79,7 +79,7 @@ static int __init tsi108_eth_of_init(void) ...@@ -79,7 +79,7 @@ static int __init tsi108_eth_of_init(void)
hw_info tsi_eth_data; hw_info tsi_eth_data;
unsigned int *id; unsigned int *id;
unsigned int *phy_id; unsigned int *phy_id;
void *mac_addr; const void *mac_addr;
phandle *ph; phandle *ph;
memset(r, 0, sizeof(r)); memset(r, 0, sizeof(r));
......
...@@ -154,8 +154,8 @@ do_relocate_out: ...@@ -154,8 +154,8 @@ do_relocate_out:
start_ldr: start_ldr:
/* Clear all of BSS and set up stack for C calls */ /* Clear all of BSS and set up stack for C calls */
lis r3,edata@h lis r3,__bss_start@h
ori r3,r3,edata@l ori r3,r3,__bss_start@l
lis r4,end@h lis r4,end@h
ori r4,r4,end@l ori r4,r4,end@l
subi r3,r3,4 subi r3,r3,4
...@@ -163,7 +163,7 @@ start_ldr: ...@@ -163,7 +163,7 @@ start_ldr:
li r0,0 li r0,0
50: stwu r0,4(r3) 50: stwu r0,4(r3)
cmpw cr0,r3,r4 cmpw cr0,r3,r4
bne 50b blt 50b
90: mr r9,r1 /* Save old stack pointer (in case it matters) */ 90: mr r9,r1 /* Save old stack pointer (in case it matters) */
lis r1,.stack@h lis r1,.stack@h
ori r1,r1,.stack@l ori r1,r1,.stack@l
......
...@@ -109,80 +109,6 @@ _GLOBAL(reloc_got2) ...@@ -109,80 +109,6 @@ _GLOBAL(reloc_got2)
mtlr r11 mtlr r11
blr blr
/*
* identify_cpu,
* called with r3 = data offset and r4 = CPU number
* doesn't change r3
*/
_GLOBAL(identify_cpu)
addis r8,r3,cpu_specs@ha
addi r8,r8,cpu_specs@l
mfpvr r7
1:
lwz r5,CPU_SPEC_PVR_MASK(r8)
and r5,r5,r7
lwz r6,CPU_SPEC_PVR_VALUE(r8)
cmplw 0,r6,r5
beq 1f
addi r8,r8,CPU_SPEC_ENTRY_SIZE
b 1b
1:
addis r6,r3,cur_cpu_spec@ha
addi r6,r6,cur_cpu_spec@l
sub r8,r8,r3
stw r8,0(r6)
blr
/*
* do_cpu_ftr_fixups - goes through the list of CPU feature fixups
* and writes nop's over sections of code that don't apply for this cpu.
* r3 = data offset (not changed)
*/
_GLOBAL(do_cpu_ftr_fixups)
/* Get CPU 0 features */
addis r6,r3,cur_cpu_spec@ha
addi r6,r6,cur_cpu_spec@l
lwz r4,0(r6)
add r4,r4,r3
lwz r4,CPU_SPEC_FEATURES(r4)
/* Get the fixup table */
addis r6,r3,__start___ftr_fixup@ha
addi r6,r6,__start___ftr_fixup@l
addis r7,r3,__stop___ftr_fixup@ha
addi r7,r7,__stop___ftr_fixup@l
/* Do the fixup */
1: cmplw 0,r6,r7
bgelr
addi r6,r6,16
lwz r8,-16(r6) /* mask */
and r8,r8,r4
lwz r9,-12(r6) /* value */
cmplw 0,r8,r9
beq 1b
lwz r8,-8(r6) /* section begin */
lwz r9,-4(r6) /* section end */
subf. r9,r8,r9
beq 1b
/* write nops over the section of code */
/* todo: if large section, add a branch at the start of it */
srwi r9,r9,2
mtctr r9
add r8,r8,r3
lis r0,0x60000000@h /* nop */
3: stw r0,0(r8)
andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
beq 2f
dcbst 0,r8 /* suboptimal, but simpler */
sync
icbi 0,r8
2: addi r8,r8,4
bdnz 3b
sync /* additional sync needed on g4 */
isync
b 1b
/* /*
* call_setup_cpu - call the setup_cpu function for this cpu * call_setup_cpu - call the setup_cpu function for this cpu
* r3 = data offset, r24 = cpu number * r3 = data offset, r24 = cpu number
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <asm/nvram.h> #include <asm/nvram.h>
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/prom.h>
#define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \ #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \
defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \ defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
...@@ -53,8 +54,6 @@ ...@@ -53,8 +54,6 @@
extern void platform_init(unsigned long r3, unsigned long r4, extern void platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7); unsigned long r5, unsigned long r6, unsigned long r7);
extern void identify_cpu(unsigned long offset, unsigned long cpu);
extern void do_cpu_ftr_fixups(unsigned long offset);
extern void reloc_got2(unsigned long offset); extern void reloc_got2(unsigned long offset);
extern void ppc6xx_idle(void); extern void ppc6xx_idle(void);
...@@ -301,6 +300,7 @@ early_init(int r3, int r4, int r5) ...@@ -301,6 +300,7 @@ early_init(int r3, int r4, int r5)
{ {
unsigned long phys; unsigned long phys;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct cpu_spec *spec;
/* Default */ /* Default */
phys = offset + KERNELBASE; phys = offset + KERNELBASE;
...@@ -313,8 +313,10 @@ early_init(int r3, int r4, int r5) ...@@ -313,8 +313,10 @@ early_init(int r3, int r4, int r5)
* Identify the CPU type and fix up code sections * Identify the CPU type and fix up code sections
* that depend on which cpu we have. * that depend on which cpu we have.
*/ */
identify_cpu(offset, 0); spec = identify_cpu(offset);
do_cpu_ftr_fixups(offset); do_feature_fixups(spec->cpu_features,
PTRRELOC(&__start___ftr_fixup),
PTRRELOC(&__stop___ftr_fixup));
return phys; return phys;
} }
......
...@@ -14,6 +14,58 @@ ...@@ -14,6 +14,58 @@
# define ASM_CONST(x) __ASM_CONST(x) # define ASM_CONST(x) __ASM_CONST(x)
#endif #endif
/*
* Feature section common macros
*
* Note that the entries now contain offsets between the table entry
* and the code rather than absolute code pointers in order to be
* useable with the vdso shared library. There is also an assumption
* that values will be negative, that is, the fixup table has to be
* located after the code it fixes up.
*/
#ifdef CONFIG_PPC64
#ifdef __powerpc64__
/* 64 bits kernel, 64 bits code */
#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
99: \
.section sect,"a"; \
.align 3; \
98: \
.llong msk; \
.llong val; \
.llong label##b-98b; \
.llong 99b-98b; \
.previous
#else /* __powerpc64__ */
/* 64 bits kernel, 32 bits code (ie. vdso32) */
#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
99: \
.section sect,"a"; \
.align 3; \
98: \
.llong msk; \
.llong val; \
.long 0xffffffff; \
.long label##b-98b; \
.long 0xffffffff; \
.long 99b-98b; \
.previous
#endif /* !__powerpc64__ */
#else /* CONFIG_PPC64 */
/* 32 bits kernel, 32 bits code */
#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
99: \
.section sect,"a"; \
.align 2; \
98: \
.long msk; \
.long val; \
.long label##b-98b; \
.long 99b-98b; \
.previous
#endif /* !CONFIG_PPC64 */
#ifdef __powerpc64__ #ifdef __powerpc64__
/* operations for longs and pointers */ /* operations for longs and pointers */
......
...@@ -89,8 +89,11 @@ struct cpu_spec { ...@@ -89,8 +89,11 @@ struct cpu_spec {
extern struct cpu_spec *cur_cpu_spec; extern struct cpu_spec *cur_cpu_spec;
extern void identify_cpu(unsigned long offset, unsigned long cpu); extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
extern void do_cpu_ftr_fixups(unsigned long offset);
extern struct cpu_spec *identify_cpu(unsigned long offset);
extern void do_feature_fixups(unsigned long value, void *fixup_start,
void *fixup_end);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
...@@ -144,6 +147,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); ...@@ -144,6 +147,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
#define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000)
#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000)
#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000)
#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -332,7 +336,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); ...@@ -332,7 +336,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE) CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
...@@ -431,29 +435,12 @@ static inline int cpu_has_feature(unsigned long feature) ...@@ -431,29 +435,12 @@ static inline int cpu_has_feature(unsigned long feature)
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
#define BEGIN_FTR_SECTION 98: #define BEGIN_FTR_SECTION_NESTED(label) label:
#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(97)
#ifndef __powerpc64__ #define END_FTR_SECTION_NESTED(msk, val, label) \
MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
#define END_FTR_SECTION(msk, val) \ #define END_FTR_SECTION(msk, val) \
99: \ END_FTR_SECTION_NESTED(msk, val, 97)
.section __ftr_fixup,"a"; \
.align 2; \
.long msk; \
.long val; \
.long 98b; \
.long 99b; \
.previous
#else /* __powerpc64__ */
#define END_FTR_SECTION(msk, val) \
99: \
.section __ftr_fixup,"a"; \
.align 3; \
.llong msk; \
.llong val; \
.llong 98b; \
.llong 99b; \
.previous
#endif /* __powerpc64__ */
#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) #define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) #define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
......
...@@ -96,19 +96,16 @@ extern void machine_check_fwnmi(void); ...@@ -96,19 +96,16 @@ extern void machine_check_fwnmi(void);
/* This is true if we are using the firmware NMI handler (typically LPAR) */ /* This is true if we are using the firmware NMI handler (typically LPAR) */
extern int fwnmi_active; extern int fwnmi_active;
#else /* __ASSEMBLY__ */ extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
#define BEGIN_FW_FTR_SECTION 96: #else /* __ASSEMBLY__ */
#define BEGIN_FW_FTR_SECTION_NESTED(label) label:
#define BEGIN_FW_FTR_SECTION BEGIN_FW_FTR_SECTION_NESTED(97)
#define END_FW_FTR_SECTION_NESTED(msk, val, label) \
MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
#define END_FW_FTR_SECTION(msk, val) \ #define END_FW_FTR_SECTION(msk, val) \
97: \ END_FW_FTR_SECTION_NESTED(msk, val, 97)
.section __fw_ftr_fixup,"a"; \
.align 3; \
.llong msk; \
.llong val; \
.llong 96b; \
.llong 97b; \
.previous
#define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk)) #define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk))
#define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0) #define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0)
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifdef CONFIG_PPC_MERGE #ifdef CONFIG_PPC_MERGE
extern void i8259_init(struct device_node *node, unsigned long intack_addr); extern void i8259_init(struct device_node *node, unsigned long intack_addr);
extern unsigned int i8259_irq(void); extern unsigned int i8259_irq(void);
extern struct irq_host *i8259_get_host(void);
#else #else
extern void i8259_init(unsigned long intack_addr, int offset); extern void i8259_init(unsigned long intack_addr, int offset);
extern int i8259_irq(void); extern int i8259_irq(void);
......
...@@ -30,9 +30,9 @@ BEGIN_FTR_SECTION; \ ...@@ -30,9 +30,9 @@ BEGIN_FTR_SECTION; \
mfspr ra,SPRN_PURR; /* get processor util. reg */ \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \
END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
BEGIN_FTR_SECTION; \ BEGIN_FTR_SECTION; \
mftb ra; /* or get TB if no PURR */ \ MFTB(ra); /* or get TB if no PURR */ \
END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
ld rb,PACA_STARTPURR(r13); \ ld rb,PACA_STARTPURR(r13); \
std ra,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \
subf rb,rb,ra; /* subtract start value */ \ subf rb,rb,ra; /* subtract start value */ \
ld ra,PACA_USER_TIME(r13); \ ld ra,PACA_USER_TIME(r13); \
...@@ -45,9 +45,9 @@ BEGIN_FTR_SECTION; \ ...@@ -45,9 +45,9 @@ BEGIN_FTR_SECTION; \
mfspr ra,SPRN_PURR; /* get processor util. reg */ \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \
END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
BEGIN_FTR_SECTION; \ BEGIN_FTR_SECTION; \
mftb ra; /* or get TB if no PURR */ \ MFTB(ra); /* or get TB if no PURR */ \
END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
ld rb,PACA_STARTPURR(r13); \ ld rb,PACA_STARTPURR(r13); \
std ra,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \
subf rb,rb,ra; /* subtract start value */ \ subf rb,rb,ra; /* subtract start value */ \
ld ra,PACA_SYSTEM_TIME(r13); \ ld ra,PACA_SYSTEM_TIME(r13); \
...@@ -274,6 +274,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) ...@@ -274,6 +274,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
#define ISYNC_601 #define ISYNC_601
#endif #endif
#ifdef CONFIG_PPC_CELL
#define MFTB(dest) \
90: mftb dest; \
BEGIN_FTR_SECTION_NESTED(96); \
cmpwi dest,0; \
beq- 90b; \
END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
#else
#define MFTB(dest) mftb dest
#endif
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
#define TLBSYNC #define TLBSYNC
......
...@@ -134,7 +134,7 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev); ...@@ -134,7 +134,7 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev);
extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev); struct device_node *prev);
extern struct property *of_find_property(struct device_node *np, extern struct property *of_find_property(const struct device_node *np,
const char *name, const char *name,
int *lenp); int *lenp);
extern struct device_node *of_node_get(struct device_node *node); extern struct device_node *of_node_get(struct device_node *node);
...@@ -158,10 +158,12 @@ extern void of_detach_node(const struct device_node *); ...@@ -158,10 +158,12 @@ extern void of_detach_node(const struct device_node *);
extern void finish_device_tree(void); extern void finish_device_tree(void);
extern void unflatten_device_tree(void); extern void unflatten_device_tree(void);
extern void early_init_devtree(void *); extern void early_init_devtree(void *);
extern int device_is_compatible(struct device_node *device, const char *); extern int device_is_compatible(const struct device_node *device,
const char *);
extern int machine_is_compatible(const char *compat); extern int machine_is_compatible(const char *compat);
extern const void *get_property(struct device_node *node, const char *name, extern const void *get_property(const struct device_node *node,
int *lenp); const char *name,
int *lenp);
extern void print_properties(struct device_node *node); extern void print_properties(struct device_node *node);
extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_addr_cells(struct device_node* np);
extern int prom_n_size_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np);
......
...@@ -591,6 +591,7 @@ ...@@ -591,6 +591,7 @@
#define PV_630 0x0040 #define PV_630 0x0040
#define PV_630p 0x0041 #define PV_630p 0x0041
#define PV_970MP 0x0044 #define PV_970MP 0x0044
#define PV_970GX 0x0045
#define PV_BE 0x0070 #define PV_BE 0x0070
#define PV_PA6T 0x0090 #define PV_PA6T 0x0090
...@@ -618,10 +619,35 @@ ...@@ -618,10 +619,35 @@
: "=r" (rval)); rval;}) : "=r" (rval)); rval;})
#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)) #define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
#ifdef __powerpc64__
#ifdef CONFIG_PPC_CELL
#define mftb() ({unsigned long rval; \
asm volatile( \
"90: mftb %0;\n" \
"97: cmpwi %0,0;\n" \
" beq- 90b;\n" \
"99:\n" \
".section __ftr_fixup,\"a\"\n" \
".align 3\n" \
"98:\n" \
" .llong %1\n" \
" .llong %1\n" \
" .llong 97b-98b\n" \
" .llong 99b-98b\n" \
".previous" \
: "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG)); rval;})
#else
#define mftb() ({unsigned long rval; \ #define mftb() ({unsigned long rval; \
asm volatile("mftb %0" : "=r" (rval)); rval;}) asm volatile("mftb %0" : "=r" (rval)); rval;})
#endif /* !CONFIG_PPC_CELL */
#else /* __powerpc64__ */
#define mftbl() ({unsigned long rval; \ #define mftbl() ({unsigned long rval; \
asm volatile("mftbl %0" : "=r" (rval)); rval;}) asm volatile("mftbl %0" : "=r" (rval)); rval;})
#define mftbu() ({unsigned long rval; \
asm volatile("mftbu %0" : "=r" (rval)); rval;})
#endif /* !__powerpc64__ */
#define mttbl(v) asm volatile("mttbl %0":: "r"(v)) #define mttbl(v) asm volatile("mttbl %0":: "r"(v))
#define mttbu(v) asm volatile("mttbu %0":: "r"(v)) #define mttbu(v) asm volatile("mttbu %0":: "r"(v))
......
...@@ -82,30 +82,35 @@ struct div_result { ...@@ -82,30 +82,35 @@ struct div_result {
#define __USE_RTC() 0 #define __USE_RTC() 0
#endif #endif
/* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */ #ifdef CONFIG_PPC64
/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */
#define get_tbl get_tb
#else
static inline unsigned long get_tbl(void) static inline unsigned long get_tbl(void)
{ {
unsigned long tbl;
#if defined(CONFIG_403GCX) #if defined(CONFIG_403GCX)
unsigned long tbl;
asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); asm volatile("mfspr %0, 0x3dd" : "=r" (tbl));
return tbl;
#else #else
asm volatile("mftb %0" : "=r" (tbl)); return mftbl();
#endif #endif
return tbl;
} }
static inline unsigned int get_tbu(void) static inline unsigned int get_tbu(void)
{ {
#ifdef CONFIG_403GCX
unsigned int tbu; unsigned int tbu;
#if defined(CONFIG_403GCX)
asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); asm volatile("mfspr %0, 0x3dc" : "=r" (tbu));
return tbu;
#else #else
asm volatile("mftbu %0" : "=r" (tbu)); return mftbu();
#endif #endif
return tbu;
} }
#endif /* !CONFIG_PPC64 */
static inline unsigned int get_rtcl(void) static inline unsigned int get_rtcl(void)
{ {
...@@ -131,7 +136,7 @@ static inline u64 get_tb(void) ...@@ -131,7 +136,7 @@ static inline u64 get_tb(void)
{ {
return mftb(); return mftb();
} }
#else #else /* CONFIG_PPC64 */
static inline u64 get_tb(void) static inline u64 get_tb(void)
{ {
unsigned int tbhi, tblo, tbhi2; unsigned int tbhi, tblo, tbhi2;
...@@ -144,7 +149,7 @@ static inline u64 get_tb(void) ...@@ -144,7 +149,7 @@ static inline u64 get_tb(void)
return ((u64)tbhi << 32) | tblo; return ((u64)tbhi << 32) | tblo;
} }
#endif #endif /* !CONFIG_PPC64 */
static inline void set_tb(unsigned int upper, unsigned int lower) static inline void set_tb(unsigned int upper, unsigned int lower)
{ {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
*/ */
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/reg.h>
#define CLOCK_TICK_RATE 1024000 /* Underlying HZ */ #define CLOCK_TICK_RATE 1024000 /* Underlying HZ */
...@@ -15,13 +16,11 @@ typedef unsigned long cycles_t; ...@@ -15,13 +16,11 @@ typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void) static inline cycles_t get_cycles(void)
{ {
cycles_t ret;
#ifdef __powerpc64__ #ifdef __powerpc64__
return mftb();
__asm__ __volatile__("mftb %0" : "=r" (ret) : );
#else #else
cycles_t ret;
/* /*
* For the "cycle" counter we use the timebase lower half. * For the "cycle" counter we use the timebase lower half.
* Currently only used on SMP. * Currently only used on SMP.
...@@ -30,18 +29,19 @@ static inline cycles_t get_cycles(void) ...@@ -30,18 +29,19 @@ static inline cycles_t get_cycles(void)
ret = 0; ret = 0;
__asm__ __volatile__( __asm__ __volatile__(
"98: mftb %0\n" "97: mftb %0\n"
"99:\n" "99:\n"
".section __ftr_fixup,\"a\"\n" ".section __ftr_fixup,\"a\"\n"
".align 2\n"
"98:\n"
" .long %1\n" " .long %1\n"
" .long 0\n" " .long 0\n"
" .long 98b\n" " .long 97b-98b\n"
" .long 99b\n" " .long 99b-98b\n"
".previous" ".previous"
: "=r" (ret) : "i" (CPU_FTR_601)); : "=r" (ret) : "i" (CPU_FTR_601));
#endif
return ret; return ret;
#endif
} }
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -921,6 +921,8 @@ static int init_section_ref_ok(const char *name) ...@@ -921,6 +921,8 @@ static int init_section_ref_ok(const char *name)
".fixup", ".fixup",
".smp_locks", ".smp_locks",
".plt", /* seen on ARCH=um build on x86_64. Harmless */ ".plt", /* seen on ARCH=um build on x86_64. Harmless */
"__ftr_fixup", /* powerpc cpu feature fixup */
"__fw_ftr_fixup", /* powerpc firmware feature fixup */
NULL NULL
}; };
/* Start of section names */ /* Start of section names */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment