提交 89de09a9 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-arm

...@@ -324,7 +324,7 @@ menu "Kernel Features" ...@@ -324,7 +324,7 @@ menu "Kernel Features"
config SMP config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)" bool "Symmetric Multi-Processing (EXPERIMENTAL)"
depends on EXPERIMENTAL && BROKEN #&& n depends on EXPERIMENTAL && REALVIEW_MPCORE
help help
This enables support for systems with more than one CPU. If you have This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If a system with only one CPU, like most personal computers, say N. If
...@@ -585,7 +585,7 @@ config FPE_NWFPE ...@@ -585,7 +585,7 @@ config FPE_NWFPE
config FPE_NWFPE_XP config FPE_NWFPE_XP
bool "Support extended precision" bool "Support extended precision"
depends on FPE_NWFPE && !CPU_BIG_ENDIAN depends on FPE_NWFPE
help help
Say Y to include 80-bit support in the kernel floating-point Say Y to include 80-bit support in the kernel floating-point
emulator. Otherwise, only 32 and 64-bit support is compiled in. emulator. Otherwise, only 32 and 64-bit support is compiled in.
......
...@@ -84,63 +84,54 @@ static struct map_desc ixp2000_io_desc[] __initdata = { ...@@ -84,63 +84,54 @@ static struct map_desc ixp2000_io_desc[] __initdata = {
.virtual = IXP2000_CAP_VIRT_BASE, .virtual = IXP2000_CAP_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE),
.length = IXP2000_CAP_SIZE, .length = IXP2000_CAP_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_INTCTL_VIRT_BASE, .virtual = IXP2000_INTCTL_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE),
.length = IXP2000_INTCTL_SIZE, .length = IXP2000_INTCTL_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_PCI_CREG_VIRT_BASE, .virtual = IXP2000_PCI_CREG_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE),
.length = IXP2000_PCI_CREG_SIZE, .length = IXP2000_PCI_CREG_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_PCI_CSR_VIRT_BASE, .virtual = IXP2000_PCI_CSR_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE),
.length = IXP2000_PCI_CSR_SIZE, .length = IXP2000_PCI_CSR_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_MSF_VIRT_BASE, .virtual = IXP2000_MSF_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE),
.length = IXP2000_MSF_SIZE, .length = IXP2000_MSF_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_PCI_IO_VIRT_BASE, .virtual = IXP2000_PCI_IO_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
.length = IXP2000_PCI_IO_SIZE, .length = IXP2000_PCI_IO_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_PCI_CFG0_VIRT_BASE, .virtual = IXP2000_PCI_CFG0_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE),
.length = IXP2000_PCI_CFG0_SIZE, .length = IXP2000_PCI_CFG0_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
}, { }, {
.virtual = IXP2000_PCI_CFG1_VIRT_BASE, .virtual = IXP2000_PCI_CFG1_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE), .pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE),
.length = IXP2000_PCI_CFG1_SIZE, .length = IXP2000_PCI_CFG1_SIZE,
.type = MT_DEVICE .type = MT_IXP2000_DEVICE,
} }
}; };
void __init ixp2000_map_io(void) void __init ixp2000_map_io(void)
{ {
extern unsigned int processor_id;
/* /*
* On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE so that
* tweaking the PMDs so XCB=101. On IXP2800s we use the normal * XCB=101 (to avoid triggering erratum #66), and given that
* PMD flags. * this mode speeds up I/O accesses and we have write buffer
* flushes in the right places anyway, it doesn't hurt to use
* XCB=101 for all IXP2000s.
*/ */
if ((processor_id & 0xfffffff0) == 0x69054190) {
int i;
printk(KERN_INFO "Enabling IXP2400 erratum #66 workaround\n");
for(i=0;i<ARRAY_SIZE(ixp2000_io_desc);i++)
ixp2000_io_desc[i].type = MT_IXP2000_DEVICE;
}
iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc)); iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
/* Set slowport to 8-bit mode. */ /* Set slowport to 8-bit mode. */
......
...@@ -8,4 +8,13 @@ config MACH_REALVIEW_EB ...@@ -8,4 +8,13 @@ config MACH_REALVIEW_EB
help help
Include support for the ARM(R) RealView Emulation Baseboard platform. Include support for the ARM(R) RealView Emulation Baseboard platform.
config REALVIEW_MPCORE
bool "Support MPcore tile"
depends on MACH_REALVIEW_EB
help
Enable support for the MPCore tile on the Realview platform.
Since there are device address and interrupt differences, a
kernel built with this option enabled is not compatible with
other tiles.
endmenu endmenu
...@@ -4,3 +4,4 @@ ...@@ -4,3 +4,4 @@
obj-y := core.o clock.o obj-y := core.o clock.o
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define __ASM_ARCH_REALVIEW_H #define __ASM_ARCH_REALVIEW_H
#include <asm/hardware/amba.h> #include <asm/hardware/amba.h>
#include <asm/leds.h>
#include <asm/io.h> #include <asm/io.h>
#define __io_address(n) __io(IO_ADDRESS(n)) #define __io_address(n) __io(IO_ADDRESS(n))
......
/*
* linux/arch/arm/mach-realview/headsmp.S
*
* Copyright (c) 2003 ARM Limited
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <linux/init.h>
__INIT
/*
* Realview specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
* ready for them to initialise.
*/
ENTRY(realview_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
adr r4, 1f
ldmia r4, {r5, r6}
sub r4, r4, r5
add r6, r6, r4
pen: ldr r7, [r6]
cmp r7, r0
bne pen
/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup
1: .long .
.long pen_release
/*
* linux/arch/arm/mach-realview/platsmp.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/hardware/arm_scu.h>
#include <asm/hardware.h>
#include "core.h"
extern void realview_secondary_startup(void);
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __cpuinitdata pen_release = -1;
static unsigned int __init get_core_count(void)
{
unsigned int ncores;
ncores = __raw_readl(IO_ADDRESS(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG);
return (ncores & 0x03) + 1;
}
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* the primary core may have used a "cross call" soft interrupt
* to get this processor out of WFI in the BootMonitor - make
* sure that we are no longer being sent this soft interrupt
*/
smp_cross_call_done(cpumask_of_cpu(cpu));
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
pen_release = -1;
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* The secondary processor is waiting to be released from
* the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release.
*
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
pen_release = cpu;
flush_cache_all();
/*
* XXX
*
* This is a later addition to the booting protocol: the
* bootMonitor now puts secondary cores into WFI, so
* poke_milo() no longer gets the cores moving; we need
* to send a soft interrupt to wake the secondary core.
* Use smp_cross_call() for this, since there's little
* point duplicating the code here
*/
smp_cross_call(cpumask_of_cpu(cpu));
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
if (pen_release == -1)
break;
udelay(10);
}
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return pen_release != -1 ? -ENOSYS : 0;
}
static void __init poke_milo(void)
{
extern void secondary_startup(void);
/* nobody is to be released from the pen yet */
pen_release = -1;
/*
* write the address of secondary startup into the system-wide
* flags register, then clear the bottom two bits, which is what
* BootMonitor is waiting for
*/
#if 1
#define REALVIEW_SYS_FLAGSS_OFFSET 0x30
__raw_writel(virt_to_phys(realview_secondary_startup),
(IO_ADDRESS(REALVIEW_SYS_BASE) +
REALVIEW_SYS_FLAGSS_OFFSET));
#define REALVIEW_SYS_FLAGSC_OFFSET 0x34
__raw_writel(3,
(IO_ADDRESS(REALVIEW_SYS_BASE) +
REALVIEW_SYS_FLAGSC_OFFSET));
#endif
mb();
}
void __init smp_prepare_cpus(unsigned int max_cpus)
{
unsigned int ncores = get_core_count();
unsigned int cpu = smp_processor_id();
int i;
/* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"Realview: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) {
printk(KERN_WARNING
"Realview: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n",
ncores, NR_CPUS);
ncores = NR_CPUS;
}
smp_store_cpu_info(cpu);
/*
* are we trying to boot more cores than exist?
*/
if (max_cpus > ncores)
max_cpus = ncores;
/*
* Initialise the possible/present maps.
* cpu_possible_map describes the set of CPUs which may be present
* cpu_present_map describes the set of CPUs populated
*/
for (i = 0; i < max_cpus; i++) {
cpu_set(i, cpu_possible_map);
cpu_set(i, cpu_present_map);
}
/*
* Do we need any more CPUs? If so, then let them know where
* to start. Note that, on modern versions of MILO, the "poke"
* doesn't actually do anything until each individual core is
* sent a soft interrupt to get it out of WFI
*/
if (max_cpus > 1)
poke_milo();
}
...@@ -136,6 +136,11 @@ static struct amba_device *amba_devs[] __initdata = { ...@@ -136,6 +136,11 @@ static struct amba_device *amba_devs[] __initdata = {
static void __init gic_init_irq(void) static void __init gic_init_irq(void)
{ {
#ifdef CONFIG_REALVIEW_MPCORE
writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
writel(0x008003c0, __io_address(REALVIEW_SYS_BASE) + 0xd8);
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
#endif
gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE)); gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
} }
......
...@@ -354,7 +354,7 @@ void __init build_mem_type_table(void) ...@@ -354,7 +354,7 @@ void __init build_mem_type_table(void)
{ {
struct cachepolicy *cp; struct cachepolicy *cp;
unsigned int cr = get_cr(); unsigned int cr = get_cr();
unsigned int user_pgprot; unsigned int user_pgprot, kern_pgprot;
int cpu_arch = cpu_architecture(); int cpu_arch = cpu_architecture();
int i; int i;
...@@ -381,7 +381,7 @@ void __init build_mem_type_table(void) ...@@ -381,7 +381,7 @@ void __init build_mem_type_table(void)
} }
cp = &cache_policies[cachepolicy]; cp = &cache_policies[cachepolicy];
user_pgprot = cp->pte; kern_pgprot = user_pgprot = cp->pte;
/* /*
* ARMv6 and above have extended page tables. * ARMv6 and above have extended page tables.
...@@ -393,6 +393,7 @@ void __init build_mem_type_table(void) ...@@ -393,6 +393,7 @@ void __init build_mem_type_table(void)
*/ */
mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; mem_types[MT_ROM].prot_sect &= ~PMD_BIT4;
/* /*
* Mark cache clean areas and XIP ROM read only * Mark cache clean areas and XIP ROM read only
* from SVC mode and no access from userspace. * from SVC mode and no access from userspace.
...@@ -412,32 +413,47 @@ void __init build_mem_type_table(void) ...@@ -412,32 +413,47 @@ void __init build_mem_type_table(void)
* (iow, non-global) * (iow, non-global)
*/ */
user_pgprot |= L_PTE_ASID; user_pgprot |= L_PTE_ASID;
#ifdef CONFIG_SMP
/*
* Mark memory with the "shared" attribute for SMP systems
*/
user_pgprot |= L_PTE_SHARED;
kern_pgprot |= L_PTE_SHARED;
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
#endif
} }
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
if (cpu_arch >= CPU_ARCH_ARMv5) { if (cpu_arch >= CPU_ARCH_ARMv5) {
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; #ifndef CONFIG_SMP
mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; /*
* Only use write-through for non-SMP systems
*/
mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
#endif
} else { } else {
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte;
mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte;
mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
} }
pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
L_PTE_DIRTY | L_PTE_WRITE |
L_PTE_EXEC | kern_pgprot);
mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
mem_types[MT_ROM].prot_sect |= cp->pmd; mem_types[MT_ROM].prot_sect |= cp->pmd;
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
L_PTE_DIRTY | L_PTE_WRITE |
L_PTE_EXEC | cp->pte);
switch (cp->pmd) { switch (cp->pmd) {
case PMD_SECT_WT: case PMD_SECT_WT:
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/hardware/arm_scu.h>
#include <asm/procinfo.h> #include <asm/procinfo.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -112,6 +113,9 @@ ENTRY(cpu_v6_dcache_clean_area) ...@@ -112,6 +113,9 @@ ENTRY(cpu_v6_dcache_clean_area)
ENTRY(cpu_v6_switch_mm) ENTRY(cpu_v6_switch_mm)
mov r2, #0 mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
#ifdef CONFIG_SMP
orr r0, r0, #2 @ set shared pgtable
#endif
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
...@@ -140,7 +144,7 @@ ENTRY(cpu_v6_switch_mm) ...@@ -140,7 +144,7 @@ ENTRY(cpu_v6_switch_mm)
ENTRY(cpu_v6_set_pte) ENTRY(cpu_v6_set_pte)
str r1, [r0], #-2048 @ linux version str r1, [r0], #-2048 @ linux version
bic r2, r1, #0x000007f0 bic r2, r1, #0x000003f0
bic r2, r2, #0x00000003 bic r2, r2, #0x00000003
orr r2, r2, #PTE_EXT_AP0 | 2 orr r2, r2, #PTE_EXT_AP0 | 2
...@@ -191,6 +195,23 @@ cpu_v6_name: ...@@ -191,6 +195,23 @@ cpu_v6_name:
* - cache type register is implemented * - cache type register is implemented
*/ */
__v6_setup: __v6_setup:
#ifdef CONFIG_SMP
/* Set up the SCU on core 0 only */
mrc p15, 0, r0, c0, c0, 5 @ CPU core number
ands r0, r0, #15
moveq r0, #0x10000000 @ SCU_BASE
orreq r0, r0, #0x00100000
ldreq r5, [r0, #SCU_CTRL]
orreq r5, r5, #1
streq r5, [r0, #SCU_CTRL]
#ifndef CONFIG_CPU_DCACHE_DISABLE
mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode
orr r0, r0, #0x20
mcr p15, 0, r0, c1, c0, 1
#endif
#endif
mov r0, #0 mov r0, #0
mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
...@@ -198,6 +219,9 @@ __v6_setup: ...@@ -198,6 +219,9 @@ __v6_setup:
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register mcr p15, 0, r0, c2, c0, 2 @ TTB control register
#ifdef CONFIG_SMP
orr r4, r4, #2 @ set shared pgtable
#endif
mcr p15, 0, r4, c2, c0, 1 @ load TTB1 mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
mrc p15, 0, r0, c1, c0, 2 mrc p15, 0, r0, c1, c0, 2
......
...@@ -60,7 +60,7 @@ typedef union tagFPREG { ...@@ -60,7 +60,7 @@ typedef union tagFPREG {
#ifdef CONFIG_FPE_NWFPE_XP #ifdef CONFIG_FPE_NWFPE_XP
floatx80 fExtended; floatx80 fExtended;
#else #else
int padding[3]; u32 padding[3];
#endif #endif
} FPREG; } FPREG;
......
...@@ -59,8 +59,13 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int __user ...@@ -59,8 +59,13 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int __user
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
fpa11->fType[Fn] = typeExtended; fpa11->fType[Fn] = typeExtended;
get_user(p[0], &pMem[0]); /* sign & exponent */ get_user(p[0], &pMem[0]); /* sign & exponent */
#ifdef __ARMEB__
get_user(p[1], &pMem[1]); /* ms bits */
get_user(p[2], &pMem[2]); /* ls bits */
#else
get_user(p[1], &pMem[2]); /* ls bits */ get_user(p[1], &pMem[2]); /* ls bits */
get_user(p[2], &pMem[1]); /* ms bits */ get_user(p[2], &pMem[1]); /* ms bits */
#endif
} }
#endif #endif
...@@ -177,8 +182,13 @@ static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMe ...@@ -177,8 +182,13 @@ static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMe
} }
put_user(val.i[0], &pMem[0]); /* sign & exp */ put_user(val.i[0], &pMem[0]); /* sign & exp */
#ifdef __ARMEB__
put_user(val.i[1], &pMem[1]); /* msw */
put_user(val.i[2], &pMem[2]);
#else
put_user(val.i[1], &pMem[2]); put_user(val.i[1], &pMem[2]);
put_user(val.i[2], &pMem[1]); /* msw */ put_user(val.i[2], &pMem[1]); /* msw */
#endif
} }
#endif #endif
......
...@@ -29,14 +29,14 @@ ...@@ -29,14 +29,14 @@
#ifdef CONFIG_FPE_NWFPE_XP #ifdef CONFIG_FPE_NWFPE_XP
const floatx80 floatx80Constant[] = { const floatx80 floatx80Constant[] = {
{0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ { .high = 0x0000, .low = 0x0000000000000000ULL},/* extended 0.0 */
{0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ { .high = 0x3fff, .low = 0x8000000000000000ULL},/* extended 1.0 */
{0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ { .high = 0x4000, .low = 0x8000000000000000ULL},/* extended 2.0 */
{0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ { .high = 0x4000, .low = 0xc000000000000000ULL},/* extended 3.0 */
{0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ { .high = 0x4001, .low = 0x8000000000000000ULL},/* extended 4.0 */
{0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ { .high = 0x4001, .low = 0xa000000000000000ULL},/* extended 5.0 */
{0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ { .high = 0x3ffe, .low = 0x8000000000000000ULL},/* extended 0.5 */
{0x4002, 0xa000000000000000ULL} /* extended 10.0 */ { .high = 0x4002, .low = 0xa000000000000000ULL},/* extended 10.0 */
}; };
#endif #endif
......
...@@ -332,6 +332,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a ) ...@@ -332,6 +332,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a )
z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
z.__padding = 0;
return z; return z;
} }
......
...@@ -531,6 +531,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) ...@@ -531,6 +531,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
z.low = zSig; z.low = zSig;
z.high = ( ( (bits16) zSign )<<15 ) + zExp; z.high = ( ( (bits16) zSign )<<15 ) + zExp;
z.__padding = 0;
return z; return z;
} }
...@@ -2831,6 +2832,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo ...@@ -2831,6 +2832,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo
roundData->exception |= float_flag_invalid; roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low; z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high; z.high = floatx80_default_nan_high;
z.__padding = 0;
return z; return z;
} }
if ( aExp == 0 ) { if ( aExp == 0 ) {
...@@ -2950,6 +2952,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) ...@@ -2950,6 +2952,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
roundData->exception |= float_flag_invalid; roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low; z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high; z.high = floatx80_default_nan_high;
z.__padding = 0;
return z; return z;
} }
return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
...@@ -3015,6 +3018,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) ...@@ -3015,6 +3018,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
roundData->exception |= float_flag_invalid; roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low; z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high; z.high = floatx80_default_nan_high;
z.__padding = 0;
return z; return z;
} }
roundData->exception |= float_flag_divbyzero; roundData->exception |= float_flag_divbyzero;
...@@ -3093,6 +3097,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) ...@@ -3093,6 +3097,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
roundData->exception |= float_flag_invalid; roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low; z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high; z.high = floatx80_default_nan_high;
z.__padding = 0;
return z; return z;
} }
normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
...@@ -3184,6 +3189,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) ...@@ -3184,6 +3189,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
roundData->exception |= float_flag_invalid; roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low; z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high; z.high = floatx80_default_nan_high;
z.__padding = 0;
return z; return z;
} }
if ( aExp == 0 ) { if ( aExp == 0 ) {
......
...@@ -51,11 +51,17 @@ input or output the `floatx80' type will be defined. ...@@ -51,11 +51,17 @@ input or output the `floatx80' type will be defined.
Software IEC/IEEE floating-point types. Software IEC/IEEE floating-point types.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
typedef unsigned long int float32; typedef u32 float32;
typedef unsigned long long float64; typedef u64 float64;
typedef struct { typedef struct {
unsigned short high; #ifdef __ARMEB__
unsigned long long low; u16 __padding;
u16 high;
#else
u16 high;
u16 __padding;
#endif
u64 low;
} floatx80; } floatx80;
/* /*
......
...@@ -47,3 +47,17 @@ ...@@ -47,3 +47,17 @@
cmpcs \irqnr, \irqnr cmpcs \irqnr, \irqnr
.endm .endm
/* We assume that irqstat (the raw value of the IRQ acknowledge
* register) is preserved from the macro above.
* If there is an IPI, we immediately signal end of interrupt on the
* controller, since this requires the original irqstat value which
* we won't easily be able to recreate later.
*/
.macro test_for_ipi, irqnr, irqstat, base, tmp
bic \irqnr, \irqstat, #0x1c00
cmp \irqnr, #16
strcc \irqstat, [\base, #GIC_CPU_EOI]
cmpcs \irqnr, \irqnr
.endm
...@@ -203,8 +203,14 @@ ...@@ -203,8 +203,14 @@
/* Reserved 0x1001A000 - 0x1001FFFF */ /* Reserved 0x1001A000 - 0x1001FFFF */
#define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ #define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */
#define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */ #define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */
#ifndef CONFIG_REALVIEW_MPCORE
#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
#else
#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */
#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
#endif
#define REALVIEW_SMC_BASE 0x10080000 /* SMC */ #define REALVIEW_SMC_BASE 0x10080000 /* SMC */
/* Reserved 0x10090000 - 0x100EFFFF */ /* Reserved 0x10090000 - 0x100EFFFF */
...@@ -265,6 +271,7 @@ ...@@ -265,6 +271,7 @@
* Interrupts - bit assignment (primary) * Interrupts - bit assignment (primary)
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
#ifndef CONFIG_REALVIEW_MPCORE
#define INT_WDOGINT 0 /* Watchdog timer */ #define INT_WDOGINT 0 /* Watchdog timer */
#define INT_SOFTINT 1 /* Software interrupt */ #define INT_SOFTINT 1 /* Software interrupt */
#define INT_COMMRx 2 /* Debug Comm Rx interrupt */ #define INT_COMMRx 2 /* Debug Comm Rx interrupt */
...@@ -297,6 +304,55 @@ ...@@ -297,6 +304,55 @@
#define INT_USB 29 /* USB controller */ #define INT_USB 29 /* USB controller */
#define INT_TSPENINT 30 /* Touchscreen pen */ #define INT_TSPENINT 30 /* Touchscreen pen */
#define INT_TSKPADINT 31 /* Touchscreen keypad */ #define INT_TSKPADINT 31 /* Touchscreen keypad */
#else
#define INT_LOCALTIMER 29
#define INT_LOCALWDOG 30
#define INT_AACI 0
#define INT_TIMERINT0_1 1
#define INT_TIMERINT2_3 2
#define INT_USB 3
#define INT_UARTINT0 4
#define INT_UARTINT1 5
#define INT_RTCINT 6
#define INT_KMI0 7
#define INT_KMI1 8
#define INT_ETH 9
#define INT_EB_IRQ1 10 /* main GIC */
#define INT_EB_IRQ2 11 /* tile GIC */
#define INT_EB_FIQ1 12 /* main GIC */
#define INT_EB_FIQ2 13 /* tile GIC */
#define INT_MMCI0A 14
#define INT_MMCI0B 15
#define INT_PMU_CPU0 17
#define INT_PMU_CPU1 18
#define INT_PMU_CPU2 19
#define INT_PMU_CPU3 20
#define INT_PMU_SCU0 21
#define INT_PMU_SCU1 22
#define INT_PMU_SCU2 23
#define INT_PMU_SCU3 24
#define INT_PMU_SCU4 25
#define INT_PMU_SCU5 26
#define INT_PMU_SCU6 27
#define INT_PMU_SCU7 28
#define INT_L220_EVENT 29
#define INT_L220_SLAVE 30
#define INT_L220_DECODE 31
#define INT_UARTINT2 -1
#define INT_UARTINT3 -1
#define INT_CLCDINT -1
#define INT_DMAINT -1
#define INT_WDOGINT -1
#define INT_GPIOINT0 -1
#define INT_GPIOINT1 -1
#define INT_GPIOINT2 -1
#define INT_SCIINT -1
#define INT_SSPINT -1
#endif
/* /*
* Interrupt bit positions * Interrupt bit positions
......
#ifndef ASMARM_ARCH_SMP_H
#define ASMARM_ARCH_SMP_H
#include <linux/config.h>
#include <asm/hardware/gic.h>
#define hard_smp_processor_id() \
({ \
unsigned int cpunum; \
__asm__("mrc p15, 0, %0, c0, c0, 5" \
: "=r" (cpunum)); \
cpunum &= 0x0F; \
})
/*
* We use IRQ1 as the IPI
*/
static inline void smp_cross_call(cpumask_t callmap)
{
gic_raise_softirq(callmap, 1);
}
/*
* Do nothing on MPcore.
*/
static inline void smp_cross_call_done(cpumask_t callmap)
{
}
#endif
#ifndef ASMARM_HARDWARE_ARM_SCU_H
#define ASMARM_HARDWARE_ARM_SCU_H
/*
* SCU registers
*/
#define SCU_CTRL 0x00
#define SCU_CONFIG 0x04
#define SCU_CPU_STATUS 0x08
#define SCU_INVALIDATE 0x0c
#define SCU_FPGA_REVISION 0x10
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册