diff options
-rw-r--r-- | arch/arm/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-ixp2000/core.c | 35 | ||||
-rw-r--r-- | arch/arm/mach-realview/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/mach-realview/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-realview/core.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-realview/headsmp.S | 39 | ||||
-rw-r--r-- | arch/arm/mach-realview/platsmp.c | 195 | ||||
-rw-r--r-- | arch/arm/mach-realview/realview_eb.c | 5 | ||||
-rw-r--r-- | arch/arm/mm/mm-armv.c | 48 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 26 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11.h | 2 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11_cpdt.c | 10 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpopcode.c | 16 | ||||
-rw-r--r-- | arch/arm/nwfpe/softfloat-specialize | 1 | ||||
-rw-r--r-- | arch/arm/nwfpe/softfloat.c | 6 | ||||
-rw-r--r-- | arch/arm/nwfpe/softfloat.h | 14 | ||||
-rw-r--r-- | include/asm-arm/arch-realview/entry-macro.S | 14 | ||||
-rw-r--r-- | include/asm-arm/arch-realview/platform.h | 56 | ||||
-rw-r--r-- | include/asm-arm/arch-realview/smp.h | 31 | ||||
-rw-r--r-- | include/asm-arm/hardware/arm_scu.h | 13 |
20 files changed, 472 insertions, 54 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 296bc03..91d5ef3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -324,7 +324,7 @@ menu "Kernel Features" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN #&& n + depends on EXPERIMENTAL && REALVIEW_MPCORE help 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 @@ -585,7 +585,7 @@ config FPE_NWFPE config FPE_NWFPE_XP bool "Support extended precision" - depends on FPE_NWFPE && !CPU_BIG_ENDIAN + depends on FPE_NWFPE help Say Y to include 80-bit support in the kernel floating-point emulator. Otherwise, only 32 and 64-bit support is compiled in. diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index df14096..6851aba 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -84,63 +84,54 @@ static struct map_desc ixp2000_io_desc[] __initdata = { .virtual = IXP2000_CAP_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE), .length = IXP2000_CAP_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_INTCTL_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE), .length = IXP2000_INTCTL_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CREG_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE), .length = IXP2000_PCI_CREG_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CSR_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE), .length = IXP2000_PCI_CSR_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_MSF_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), .length = IXP2000_MSF_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_IO_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), .length = IXP2000_PCI_IO_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CFG0_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE), .length = IXP2000_PCI_CFG0_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CFG1_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE), .length = IXP2000_PCI_CFG1_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, } }; void __init ixp2000_map_io(void) { - extern unsigned int processor_id; - /* - * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for - * tweaking the PMDs so XCB=101. On IXP2800s we use the normal - * PMD flags. + * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE so that + * XCB=101 (to avoid triggering erratum #66), and given that + * 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)); /* Set slowport to 8-bit mode. */ diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 4b63dc9..1299768 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -8,4 +8,13 @@ config MACH_REALVIEW_EB help 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 diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 8d37ea1..011a85c 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -4,3 +4,4 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 575599d..d83e8ba 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -23,6 +23,7 @@ #define __ASM_ARCH_REALVIEW_H #include <asm/hardware/amba.h> +#include <asm/leds.h> #include <asm/io.h> #define __io_address(n) __io(IO_ADDRESS(n)) diff --git a/arch/arm/mach-realview/headsmp.S b/arch/arm/mach-realview/headsmp.S new file mode 100644 index 0000000..4075473 --- /dev/null +++ b/arch/arm/mach-realview/headsmp.S @@ -0,0 +1,39 @@ +/* + * 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 diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c new file mode 100644 index 0000000..9844644 --- /dev/null +++ b/arch/arm/mach-realview/platsmp.c @@ -0,0 +1,195 @@ +/* + * 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(); +} diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 267bb07..7dc3250 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -136,6 +136,11 @@ static struct amba_device *amba_devs[] __initdata = { 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_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); } diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index fb5b402..9e50127 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -354,7 +354,7 @@ void __init build_mem_type_table(void) { struct cachepolicy *cp; unsigned int cr = get_cr(); - unsigned int user_pgprot; + unsigned int user_pgprot, kern_pgprot; int cpu_arch = cpu_architecture(); int i; @@ -381,7 +381,7 @@ void __init build_mem_type_table(void) } cp = &cache_policies[cachepolicy]; - user_pgprot = cp->pte; + kern_pgprot = user_pgprot = cp->pte; /* * ARMv6 and above have extended page tables. @@ -393,6 +393,7 @@ void __init build_mem_type_table(void) */ mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; + /* * Mark cache clean areas and XIP ROM read only * from SVC mode and no access from userspace. @@ -412,32 +413,47 @@ void __init build_mem_type_table(void) * (iow, non-global) */ 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) { - mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; - mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; +#ifndef CONFIG_SMP + /* + * 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 { - 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); } + 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_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | 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) { case PMD_SECT_WT: mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 9bb5fff..92f3ca3 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -12,6 +12,7 @@ #include <linux/linkage.h> #include <asm/assembler.h> #include <asm/asm-offsets.h> +#include <asm/hardware/arm_scu.h> #include <asm/procinfo.h> #include <asm/pgtable.h> @@ -112,6 +113,9 @@ ENTRY(cpu_v6_dcache_clean_area) ENTRY(cpu_v6_switch_mm) mov r2, #0 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, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -140,7 +144,7 @@ ENTRY(cpu_v6_switch_mm) ENTRY(cpu_v6_set_pte) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0x000007f0 + bic r2, r1, #0x000003f0 bic r2, r2, #0x00000003 orr r2, r2, #PTE_EXT_AP0 | 2 @@ -191,6 +195,23 @@ cpu_v6_name: * - cache type register is implemented */ __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 mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache @@ -198,6 +219,9 @@ __v6_setup: 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, 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 #ifdef CONFIG_VFP mrc p15, 0, r0, c1, c0, 2 diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index 9677ae8..da4c616 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -60,7 +60,7 @@ typedef union tagFPREG { #ifdef CONFIG_FPE_NWFPE_XP floatx80 fExtended; #else - int padding[3]; + u32 padding[3]; #endif } FPREG; diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index b0db5cb..32859fa 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -59,8 +59,13 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int __user p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; fpa11->fType[Fn] = typeExtended; 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[2], &pMem[1]); /* ms bits */ +#endif } #endif @@ -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 */ +#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[2], &pMem[1]); /* msw */ +#endif } #endif diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c index 4c9f570..67ff2ab 100644 --- a/arch/arm/nwfpe/fpopcode.c +++ b/arch/arm/nwfpe/fpopcode.c @@ -29,14 +29,14 @@ #ifdef CONFIG_FPE_NWFPE_XP const floatx80 floatx80Constant[] = { - {0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ - {0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ - {0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ - {0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ - {0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ - {0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ - {0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ - {0x4002, 0xa000000000000000ULL} /* extended 10.0 */ + { .high = 0x0000, .low = 0x0000000000000000ULL},/* extended 0.0 */ + { .high = 0x3fff, .low = 0x8000000000000000ULL},/* extended 1.0 */ + { .high = 0x4000, .low = 0x8000000000000000ULL},/* extended 2.0 */ + { .high = 0x4000, .low = 0xc000000000000000ULL},/* extended 3.0 */ + { .high = 0x4001, .low = 0x8000000000000000ULL},/* extended 4.0 */ + { .high = 0x4001, .low = 0xa000000000000000ULL},/* extended 5.0 */ + { .high = 0x3ffe, .low = 0x8000000000000000ULL},/* extended 0.5 */ + { .high = 0x4002, .low = 0xa000000000000000ULL},/* extended 10.0 */ }; #endif diff --git a/arch/arm/nwfpe/softfloat-specialize b/arch/arm/nwfpe/softfloat-specialize index acf4091..d4a4c8e 100644 --- a/arch/arm/nwfpe/softfloat-specialize +++ b/arch/arm/nwfpe/softfloat-specialize @@ -332,6 +332,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a ) z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + z.__padding = 0; return z; } diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c index f9f0491..0f9656e 100644 --- a/arch/arm/nwfpe/softfloat.c +++ b/arch/arm/nwfpe/softfloat.c @@ -531,6 +531,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) z.low = zSig; z.high = ( ( (bits16) zSign )<<15 ) + zExp; + z.__padding = 0; return z; } @@ -2831,6 +2832,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } if ( aExp == 0 ) { @@ -2950,6 +2952,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); @@ -3015,6 +3018,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } roundData->exception |= float_flag_divbyzero; @@ -3093,6 +3097,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); @@ -3184,6 +3189,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } if ( aExp == 0 ) { diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 1415170..978c699 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -51,11 +51,17 @@ input or output the `floatx80' type will be defined. Software IEC/IEEE floating-point types. ------------------------------------------------------------------------------- */ -typedef unsigned long int float32; -typedef unsigned long long float64; +typedef u32 float32; +typedef u64 float64; typedef struct { - unsigned short high; - unsigned long long low; +#ifdef __ARMEB__ + u16 __padding; + u16 high; +#else + u16 high; + u16 __padding; +#endif + u64 low; } floatx80; /* diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 2712ba7..4df469b 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -47,3 +47,17 @@ cmpcs \irqnr, \irqnr .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 diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 4b6de13..aef9b36 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -203,8 +203,14 @@ /* Reserved 0x1001A000 - 0x1001FFFF */ #define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ #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_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 */ /* Reserved 0x10090000 - 0x100EFFFF */ @@ -265,6 +271,7 @@ * Interrupts - bit assignment (primary) * ------------------------------------------------------------------------ */ +#ifndef CONFIG_REALVIEW_MPCORE #define INT_WDOGINT 0 /* Watchdog timer */ #define INT_SOFTINT 1 /* Software interrupt */ #define INT_COMMRx 2 /* Debug Comm Rx interrupt */ @@ -297,6 +304,55 @@ #define INT_USB 29 /* USB controller */ #define INT_TSPENINT 30 /* Touchscreen pen */ #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 diff --git a/include/asm-arm/arch-realview/smp.h b/include/asm-arm/arch-realview/smp.h new file mode 100644 index 0000000..fc87783 --- /dev/null +++ b/include/asm-arm/arch-realview/smp.h @@ -0,0 +1,31 @@ +#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 diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h new file mode 100644 index 0000000..9903f60 --- /dev/null +++ b/include/asm-arm/hardware/arm_scu.h @@ -0,0 +1,13 @@ +#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 |