summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Makefile3
-rw-r--r--arch/arm/common/dmabounce.c8
-rw-r--r--arch/arm/common/rtctime.c1
-rw-r--r--arch/arm/common/sa1111.c6
-rw-r--r--arch/arm/kernel/Makefile3
-rw-r--r--arch/arm/kernel/entry-armv.S21
-rw-r--r--arch/arm/kernel/head.S2
-rw-r--r--arch/arm/kernel/isa.c63
-rw-r--r--arch/arm/kernel/traps.c2
-rw-r--r--arch/arm/mach-footbridge/dc21285.c1
-rw-r--r--arch/arm/mach-integrator/pci_v3.c2
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c2
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c7
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c20
-rw-r--r--arch/arm/mach-pxa/ssp.c35
-rw-r--r--arch/arm/mach-s3c2410/Makefile36
-rw-r--r--arch/arm/mach-s3c2410/dma.c163
-rw-r--r--arch/arm/mach-sa1100/ssp.c46
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--arch/arm/mm/Kconfig13
-rw-r--r--arch/arm/vfp/vfp.h8
-rw-r--r--arch/arm/vfp/vfpdouble.c30
-rw-r--r--arch/arm/vfp/vfpmodule.c4
-rw-r--r--arch/arm/vfp/vfpsingle.c35
24 files changed, 380 insertions, 133 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 3345c6d0fd1e..92873cdee31f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,7 +47,8 @@ comma = ,
# testing for a specific architecture or later rather impossible.
arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
-arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5b7c26395b44..028bdc9228fb 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -179,17 +179,19 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
static inline struct safe_buffer *
find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
{
- struct safe_buffer *b = NULL;
+ struct safe_buffer *b, *rb = NULL;
unsigned long flags;
read_lock_irqsave(&device_info->lock, flags);
list_for_each_entry(b, &device_info->safe_buffers, node)
- if (b->safe_dma_addr == safe_dma_addr)
+ if (b->safe_dma_addr == safe_dma_addr) {
+ rb = b;
break;
+ }
read_unlock_irqrestore(&device_info->lock, flags);
- return b;
+ return rb;
}
static inline void
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 35c9a64ac14c..4e5445cfb0ea 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -68,6 +68,7 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc
rtc_time_to_tm(next_time, next);
}
}
+EXPORT_SYMBOL(rtc_next_alarm_time);
static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
{
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index a331c12cead9..29818bd3248f 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -618,7 +618,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
{
struct sa1111 *sachip;
unsigned long id;
- unsigned int has_devs, val;
+ unsigned int has_devs;
int i, ret = -ENODEV;
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
@@ -669,6 +669,9 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
sa1111_wake(sachip);
#ifdef CONFIG_ARCH_SA1100
+ {
+ unsigned int val;
+
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
@@ -692,6 +695,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
+ }
#endif
/*
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index f0c0cdb1c183..1320a0efca73 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -13,12 +13,11 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o
-obj-$(CONFIG_FOOTBRIDGE) += isa.o
obj-$(CONFIG_FIQ) += fiq.o
obj-$(CONFIG_MODULES) += armksyms.o module.o
obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
-obj-$(CONFIG_PCI) += bios32.o
+obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7ea5f01dfc7b..de4e33137901 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -634,6 +634,14 @@ ENTRY(__switch_to)
* purpose.
*/
+ .macro usr_ret, reg
+#ifdef CONFIG_ARM_THUMB
+ bx \reg
+#else
+ mov pc, \reg
+#endif
+ .endm
+
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
@@ -675,7 +683,7 @@ __kuser_memory_barrier: @ 0xffff0fa0
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_SMP)
mcr p15, 0, r0, c7, c10, 5 @ dmb
#endif
- mov pc, lr
+ usr_ret lr
.align 5
@@ -778,7 +786,7 @@ __kuser_cmpxchg: @ 0xffff0fc0
mov r0, #-1
adds r0, r0, #0
#endif
- mov pc, lr
+ usr_ret lr
#else
@@ -792,7 +800,7 @@ __kuser_cmpxchg: @ 0xffff0fc0
#ifdef CONFIG_SMP
mcr p15, 0, r0, c7, c10, 5 @ dmb
#endif
- mov pc, lr
+ usr_ret lr
#endif
@@ -834,16 +842,11 @@ __kuser_cmpxchg: @ 0xffff0fc0
__kuser_get_tls: @ 0xffff0fe0
#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
-
ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0
- mov pc, lr
-
#else
-
mrc p15, 0, r0, c13, c0, 3 @ read TLS register
- mov pc, lr
-
#endif
+ usr_ret lr
.rep 5
.word 0 @ pad up to __kuser_helper_version
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4fe386eea4b4..5365d4e5949e 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -118,7 +118,7 @@ ENTRY(secondary_startup)
sub r4, r4, r5 @ mmu has been enabled
ldr r4, [r7, r4] @ get secondary_data.pgdir
adr lr, __enable_mmu @ return address
- add pc, r10, #12 @ initialise processor
+ add pc, r10, #PROCINFO_INITFUNC @ initialise processor
@ (return control reg)
/*
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 685c3e591a7e..54bbd9fe255c 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -3,21 +3,14 @@
*
* Copyright (C) 1999 Phil Blundell
*
- * ISA shared memory and I/O port support
- */
-
-/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * ISA shared memory and I/O port support, and is required to support
+ * iopl, inb, outb and friends in userspace via glibc emulation.
*/
-
-/*
- * Nothing about this is actually ARM specific. One day we could move
- * it into kernel/resource.c or some place like that.
- */
-
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/fs.h>
@@ -27,21 +20,49 @@
static unsigned int isa_membase, isa_portbase, isa_portshift;
static ctl_table ctl_isa_vars[4] = {
- {BUS_ISA_MEM_BASE, "membase", &isa_membase,
- sizeof(isa_membase), 0444, NULL, &proc_dointvec},
- {BUS_ISA_PORT_BASE, "portbase", &isa_portbase,
- sizeof(isa_portbase), 0444, NULL, &proc_dointvec},
- {BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift,
- sizeof(isa_portshift), 0444, NULL, &proc_dointvec},
- {0}
+ {
+ .ctl_name = BUS_ISA_MEM_BASE,
+ .procname = "membase",
+ .data = &isa_membase,
+ .maxlen = sizeof(isa_membase),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {
+ .ctl_name = BUS_ISA_PORT_BASE,
+ .procname = "portbase",
+ .data = &isa_portbase,
+ .maxlen = sizeof(isa_portbase),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {
+ .ctl_name = BUS_ISA_PORT_SHIFT,
+ .procname = "portshift",
+ .data = &isa_portshift,
+ .maxlen = sizeof(isa_portshift),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {0}
};
static struct ctl_table_header *isa_sysctl_header;
-static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
- {0}};
-static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
- {0}};
+static ctl_table ctl_isa[2] = {
+ {
+ .ctl_name = CTL_BUS_ISA,
+ .procname = "isa",
+ .mode = 0555,
+ .child = ctl_isa_vars,
+ }, {0}
+};
+
+static ctl_table ctl_bus[2] = {
+ {
+ .ctl_name = CTL_BUS,
+ .procname = "bus",
+ .mode = 0555,
+ .child = ctl_isa,
+ }, {0}
+};
void __init
register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 4e29dd03e582..aeeed806f991 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -233,7 +233,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
spin_unlock_irq(&die_lock);
if (panic_on_oops)
- panic("Fatal exception: panic_on_oops");
+ panic("Fatal exception");
do_exit(SIGSEGV);
}
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 607ed1f5b3f8..823e25d4547e 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -35,7 +35,6 @@
extern int setup_arm_irq(int, struct irqaction *);
extern void pcibios_report_status(u_int status_mask, int warn);
-extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
static unsigned long
dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index f9043592e299..4418f6d7572d 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -600,4 +600,6 @@ void __init pci_v3_postinit(void)
printk(KERN_ERR "PCI: unable to grab local bus timeout "
"interrupt: %d\n", ret);
#endif
+
+ register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
}
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 2d40fe1145f0..9562177b5fe1 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -532,8 +532,6 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
return -EIO;
}
-EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_set_consistent_dma_mask);
EXPORT_SYMBOL(ixp4xx_pci_read);
EXPORT_SYMBOL(ixp4xx_pci_write);
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 654e2eed81fb..30f1300e0e21 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -107,9 +107,9 @@ static struct flash_platform_data gtwx5715_flash_data = {
.width = 2,
};
-static struct gtw5715_flash_resource = {
+static struct resource gtwx5715_flash_resource = {
.flags = IORESOURCE_MEM,
-}
+};
static struct platform_device gtwx5715_flash = {
.name = "IXP4XX-Flash",
@@ -130,9 +130,6 @@ static void __init gtwx5715_init(void)
{
ixp4xx_sys_init();
- if (!flash_resource)
- printk(KERN_ERR "Could not allocate flash resource\n");
-
gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index f9421318cb7a..ff6b4ee037f5 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -47,14 +47,15 @@ static struct corgissp_machinfo *ssp_machinfo;
*/
unsigned long corgi_ssp_ads7846_putget(ulong data)
{
- unsigned long ret,flag;
+ unsigned long flag;
+ u32 ret = 0;
spin_lock_irqsave(&corgi_ssp_lock, flag);
if (ssp_machinfo->cs_ads7846 >= 0)
GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
ssp_write_word(&corgi_ssp_dev,data);
- ret = ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, &ret);
if (ssp_machinfo->cs_ads7846 >= 0)
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
@@ -88,7 +89,9 @@ void corgi_ssp_ads7846_put(ulong data)
unsigned long corgi_ssp_ads7846_get(void)
{
- return ssp_read_word(&corgi_ssp_dev);
+ u32 ret = 0;
+ ssp_read_word(&corgi_ssp_dev, &ret);
+ return ret;
}
EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
@@ -104,6 +107,7 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get);
unsigned long corgi_ssp_dac_put(ulong data)
{
unsigned long flag, sscr1 = SSCR1_SPH;
+ u32 tmp;
spin_lock_irqsave(&corgi_ssp_lock, flag);
@@ -118,7 +122,7 @@ unsigned long corgi_ssp_dac_put(ulong data)
GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_write_word(&corgi_ssp_dev,data);
/* Read null data back from device to prevent SSP overflow */
- ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, &tmp);
if (ssp_machinfo->cs_lcdcon >= 0)
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
@@ -150,7 +154,7 @@ EXPORT_SYMBOL(corgi_ssp_blduty_set);
int corgi_ssp_max1111_get(ulong data)
{
unsigned long flag;
- int voltage,voltage1,voltage2;
+ long voltage = 0, voltage1 = 0, voltage2 = 0;
spin_lock_irqsave(&corgi_ssp_lock, flag);
if (ssp_machinfo->cs_max1111 >= 0)
@@ -163,15 +167,15 @@ int corgi_ssp_max1111_get(ulong data)
/* TB1/RB1 */
ssp_write_word(&corgi_ssp_dev,data);
- ssp_read_word(&corgi_ssp_dev); /* null read */
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */
/* TB12/RB2 */
ssp_write_word(&corgi_ssp_dev,0);
- voltage1=ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1);
/* TB13/RB3*/
ssp_write_word(&corgi_ssp_dev,0);
- voltage2=ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2);
ssp_disable(&corgi_ssp_dev);
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 93096befd017..1fddfeaa630d 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -40,6 +40,8 @@
#define PXA_SSP_PORTS 3
+#define TIMEOUT 100000
+
struct ssp_info_ {
int irq;
u32 clock;
@@ -92,13 +94,18 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 0 success
*/
int ssp_write_word(struct ssp_dev *dev, u32 data)
{
- while (!(SSSR_P(dev->port) & SSSR_TNF))
+ int timeout = TIMEOUT;
+
+ while (!(SSSR_P(dev->port) & SSSR_TNF)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
SSDR_P(dev->port) = data;
@@ -117,15 +124,21 @@ int ssp_write_word(struct ssp_dev *dev, u32 data)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 32-bit data success
*/
-int ssp_read_word(struct ssp_dev *dev)
+int ssp_read_word(struct ssp_dev *dev, u32 *data)
{
- while (!(SSSR_P(dev->port) & SSSR_RNE))
+ int timeout = TIMEOUT;
+
+ while (!(SSSR_P(dev->port) & SSSR_RNE)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
- return SSDR_P(dev->port);
+ *data = SSDR_P(dev->port);
+ return 0;
}
/**
@@ -136,13 +149,21 @@ int ssp_read_word(struct ssp_dev *dev)
*
* The caller is expected to perform the necessary locking.
*/
-void ssp_flush(struct ssp_dev *dev)
+int ssp_flush(struct ssp_dev *dev)
{
+ int timeout = TIMEOUT * 2;
+
do {
while (SSSR_P(dev->port) & SSSR_RNE) {
+ if (!--timeout)
+ return -ETIMEDOUT;
(void) SSDR_P(dev->port);
}
+ if (!--timeout)
+ return -ETIMEDOUT;
} while (SSSR_P(dev->port) & SSSR_BSY);
+
+ return 0;
}
/**
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 0c7938645df6..273e05f2b8de 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -10,45 +10,47 @@ obj-m :=
obj-n :=
obj- :=
+# DMA
+obj-$(CONFIG_S3C2410_DMA) += dma.o
+
# S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
+obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
# S3C2410 support files
-obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
-obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o
-obj-$(CONFIG_S3C2410_DMA) += dma.o
+obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
+obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o
# Power Management support
-obj-$(CONFIG_PM) += pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
+obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
# S3C2412 support
-obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
-obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
+obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
#
# S3C244X support
-obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
-obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
+obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
# Clock control
-obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
+obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
# S3C2440 support
-obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o
+obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
+obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
+obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
+obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o
# S3C2442 support
-obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
-obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o
+obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o
# bast extras
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 094cc52745c5..25855452fe8c 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -112,7 +112,7 @@ dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
}
static void
-dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
+dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
struct s3c2410_dma_regstate *regs)
{
printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
@@ -132,7 +132,16 @@ dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
chan->number, fname, line, chan->load_state,
chan->curr, chan->next, chan->end);
- dmadbg_showregs(fname, line, chan, &state);
+ dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan)
+{
+ struct s3c2410_dma_regstate state;
+
+ dmadbg_capture(chan, &state);
+ dmadbg_dumpregs(fname, line, chan, &state);
}
#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
@@ -253,10 +262,14 @@ s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
buf->next);
reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
} else {
- pr_debug("load_state is %d => autoreload\n", chan->load_state);
+ //pr_debug("load_state is %d => autoreload\n", chan->load_state);
reload = S3C2410_DCON_AUTORELOAD;
}
+ if ((buf->data & 0xf0000000) != 0x30000000) {
+ dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+ }
+
writel(buf->data, chan->addr_reg);
dma_wrreg(chan, S3C2410_DMA_DCON,
@@ -370,7 +383,7 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
tmp |= S3C2410_DMASKTRIG_ON;
dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
- pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
+ pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
#if 0
/* the dma buffer loads should take care of clearing the AUTO
@@ -384,7 +397,30 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
dbg_showchan(chan);
+ /* if we've only loaded one buffer onto the channel, then chec
+ * to see if we have another, and if so, try and load it so when
+ * the first buffer is finished, the new one will be loaded onto
+ * the channel */
+
+ if (chan->next != NULL) {
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ pr_debug("%s: buff not yet loaded, no more todo\n",
+ __FUNCTION__);
+ } else {
+ chan->load_state = S3C2410_DMALOAD_1RUNNING;
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+
+ } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+ }
+
+
local_irq_restore(flags);
+
return 0;
}
@@ -436,12 +472,11 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
if (buf == NULL) {
pr_debug("%s: out of memory (%ld alloc)\n",
- __FUNCTION__, sizeof(*buf));
+ __FUNCTION__, (long)sizeof(*buf));
return -ENOMEM;
}
- pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
-
+ //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
//dbg_showchan(chan);
buf->next = NULL;
@@ -537,14 +572,20 @@ s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
case S3C2410_DMALOAD_1LOADED:
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
/* flag error? */
- printk(KERN_ERR "dma%d: timeout waiting for load\n",
- chan->number);
+ printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+ chan->number, __FUNCTION__);
return;
}
break;
+ case S3C2410_DMALOAD_1LOADED_1RUNNING:
+ /* I belive in this case we do not have anything to do
+ * until the next buffer comes along, and we turn off the
+ * reload */
+ return;
+
default:
- pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
+ pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
chan->number, chan->load_state);
return;
@@ -629,7 +670,14 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
} else {
}
- if (chan->next != NULL) {
+ /* only reload if the channel is still running... our buffer done
+ * routine may have altered the state by requesting the dma channel
+ * to stop or shutdown... */
+
+ /* todo: check that when the channel is shut-down from inside this
+ * function, we cope with unsetting reload, etc */
+
+ if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
unsigned long flags;
switch (chan->load_state) {
@@ -644,8 +692,8 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
case S3C2410_DMALOAD_1LOADED:
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
/* flag error? */
- printk(KERN_ERR "dma%d: timeout waiting for load\n",
- chan->number);
+ printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+ chan->number, __FUNCTION__);
return IRQ_HANDLED;
}
@@ -678,8 +726,6 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
return IRQ_HANDLED;
}
-
-
/* s3c2410_request_dma
*
* get control of an dma channel
@@ -718,11 +764,17 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
pr_debug("dma%d: %s : requesting irq %d\n",
channel, __FUNCTION__, chan->irq);
+ chan->irq_claimed = 1;
+ local_irq_restore(flags);
+
err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
client->name, (void *)chan);
+ local_irq_save(flags);
+
if (err) {
chan->in_use = 0;
+ chan->irq_claimed = 0;
local_irq_restore(flags);
printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
@@ -730,7 +782,6 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
return err;
}
- chan->irq_claimed = 1;
chan->irq_enabled = 1;
}
@@ -810,6 +861,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
tmp |= S3C2410_DMASKTRIG_STOP;
+ //tmp &= ~S3C2410_DMASKTRIG_ON;
dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
#if 0
@@ -819,6 +871,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
#endif
+ /* should stop do this, or should we wait for flush? */
chan->state = S3C2410_DMA_IDLE;
chan->load_state = S3C2410_DMALOAD_NONE;
@@ -827,6 +880,22 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
return 0;
}
+void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan)
+{
+ unsigned long tmp;
+ unsigned int timeout = 0x10000;
+
+ while (timeout-- > 0) {
+ tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+ if (!(tmp & S3C2410_DMASKTRIG_ON))
+ return;
+ }
+
+ pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
/* s3c2410_dma_flush
*
* stop the channel, and remove all current and pending transfers
@@ -837,7 +906,9 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
s3c2410_dma_buf_t *buf, *next;
unsigned long flags;
- pr_debug("%s:\n", __FUNCTION__);
+ pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+ dbg_showchan(chan);
local_irq_save(flags);
@@ -864,11 +935,64 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
}
}
+ dbg_showregs(chan);
+
+ s3c2410_dma_waitforstop(chan);
+
+#if 0
+ /* should also clear interrupts, according to WinCE BSP */
+ {
+ unsigned long tmp;
+
+ tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+ tmp |= S3C2410_DCON_NORELOAD;
+ dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+ }
+#endif
+
+ dbg_showregs(chan);
+
local_irq_restore(flags);
return 0;
}
+int
+s3c2410_dma_started(s3c2410_dma_chan_t *chan)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ dbg_showchan(chan);
+
+ /* if we've only loaded one buffer onto the channel, then chec
+ * to see if we have another, and if so, try and load it so when
+ * the first buffer is finished, the new one will be loaded onto
+ * the channel */
+
+ if (chan->next != NULL) {
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ pr_debug("%s: buff not yet loaded, no more todo\n",
+ __FUNCTION__);
+ } else {
+ chan->load_state = S3C2410_DMALOAD_1RUNNING;
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+
+ } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+ }
+
+
+ local_irq_restore(flags);
+
+ return 0;
+
+}
int
s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
@@ -885,14 +1009,15 @@ s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
return s3c2410_dma_dostop(chan);
case S3C2410_DMAOP_PAUSE:
- return -ENOENT;
-
case S3C2410_DMAOP_RESUME:
return -ENOENT;
case S3C2410_DMAOP_FLUSH:
return s3c2410_dma_flush(chan);
+ case S3C2410_DMAOP_STARTED:
+ return s3c2410_dma_started(chan);
+
case S3C2410_DMAOP_TIMEOUT:
return 0;
diff --git a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
index 1604dadf27fc..5eba5fbbb561 100644
--- a/arch/arm/mach-sa1100/ssp.c
+++ b/arch/arm/mach-sa1100/ssp.c
@@ -23,6 +23,8 @@
#include <asm/hardware.h>
#include <asm/hardware/ssp.h>
+#define TIMEOUT 100000
+
static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int status = Ser4SSSR;
@@ -47,18 +49,27 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 0 success
*/
int ssp_write_word(u16 data)
{
- while (!(Ser4SSSR & SSSR_TNF))
+ int timeout = TIMEOUT;
+
+ while (!(Ser4SSSR & SSSR_TNF)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
Ser4SSDR = data;
- while (!(Ser4SSSR & SSSR_BSY))
+ timeout = TIMEOUT;
+ while (!(Ser4SSSR & SSSR_BSY)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
return 0;
}
@@ -75,15 +86,22 @@ int ssp_write_word(u16 data)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 16-bit data success
*/
-int ssp_read_word(void)
+int ssp_read_word(u16 *data)
{
- while (!(Ser4SSSR & SSSR_RNE))
+ int timeout = TIMEOUT;
+
+ while (!(Ser4SSSR & SSSR_RNE)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
+
+ *data = (u16)Ser4SSDR;
- return Ser4SSDR;
+ return 0;
}
/**
@@ -93,14 +111,26 @@ int ssp_read_word(void)
* is empty.
*
* The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ * %-ETIMEDOUT timeout occurred
+ * 0 success
*/
-void ssp_flush(void)
+int ssp_flush(void)
{
+ int timeout = TIMEOUT * 2;
+
do {
while (Ser4SSSR & SSSR_RNE) {
+ if (!--timeout)
+ return -ETIMEDOUT;
(void) Ser4SSDR;
}
+ if (!--timeout)
+ return -ETIMEDOUT;
} while (Ser4SSSR & SSSR_BSY);
+
+ return 0;
}
/**
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index c4e3f8c68479..f2bbef07b1e4 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -285,7 +285,7 @@ static struct flash_platform_data versatile_flash_data = {
static struct resource versatile_flash_resource = {
.start = VERSATILE_FLASH_BASE,
- .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
+ .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5f80f184cd32..b4f220dd5eb8 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -46,7 +46,7 @@ config CPU_ARM710
config CPU_ARM720T
bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_LV4T
select CPU_CACHE_V4
select CPU_CACHE_VIVT
@@ -64,7 +64,7 @@ config CPU_ARM920T
bool "Support ARM920T processor"
depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -85,7 +85,7 @@ config CPU_ARM922T
bool "Support ARM922T processor" if ARCH_INTEGRATOR
depends on ARCH_LH7A40X || ARCH_INTEGRATOR
default y if ARCH_LH7A40X
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -104,7 +104,7 @@ config CPU_ARM925T
bool "Support ARM925T processor" if ARCH_OMAP1
depends on ARCH_OMAP15XX
default y if ARCH_OMAP15XX
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -285,6 +285,11 @@ config CPU_32v4
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+config CPU_32v4T
+ bool
+ select TLS_REG_EMUL if SMP || !MMU
+ select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+
config CPU_32v5
bool
select TLS_REG_EMUL if SMP || !MMU
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 4b97950984e9..5fbdf81a8aaf 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -353,3 +353,11 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
* A special flag to tell the normalisation code not to normalise.
*/
#define VFP_NAN_FLAG 0x100
+
+/*
+ * A bit pattern used to indicate the initial (unset) value of the
+ * exception mask, in case nothing handles an instruction. This
+ * doesn't include the NAN flag, which get masked out before
+ * we check for an error.
+ */
+#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 009038c8113e..04bd3425b29b 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -465,7 +465,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
vsd.exponent = 255;
- if (tm & VFP_NAN)
+ if (tm == VFP_QNAN)
vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
goto pack_nan;
} else if (tm & VFP_ZERO)
@@ -1127,7 +1127,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int dd = vfp_get_dd(inst);
+ unsigned int dest;
unsigned int dn = vfp_get_dn(inst);
unsigned int dm = vfp_get_dm(inst);
unsigned int vecitr, veclen, vecstride;
@@ -1137,10 +1137,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
/*
+ * fcvtds takes an sN register number as destination, not dN.
+ * It also always operates on scalars.
+ */
+ if ((inst & FEXT_MASK) == FEXT_FCVT) {
+ veclen = 0;
+ dest = vfp_get_sd(inst);
+ } else
+ dest = vfp_get_dd(inst);
+
+ /*
* If destination bank is zero, vector length is always '1'.
* ARM DDI0100F C5.1.3, C5.3.2.
*/
- if (FREG_BANK(dd) == 0)
+ if (FREG_BANK(dest) == 0)
veclen = 0;
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1153,16 +1163,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
u32 except;
- if (op == FOP_EXT)
+ if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+ pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
+ vecitr >> FPSCR_LENGTH_BIT,
+ dest, dn, dm);
+ else if (op == FOP_EXT)
pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd, dn, dm);
+ dest, dn, dm);
else
pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd, dn, FOP_TO_IDX(op), dm);
+ dest, dn, FOP_TO_IDX(op), dm);
- except = fop(dd, dn, dm, fpscr);
+ except = fop(dest, dn, dm, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
vecitr >> FPSCR_LENGTH_BIT, except);
@@ -1180,7 +1194,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
* we encounter an exception. We continue.
*/
- dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6);
+ dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
if (FREG_BANK(dm) != 0)
dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 9d265d5e748c..4178f6cc3d37 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -131,7 +131,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
pr_debug("VFP: raising exceptions %08x\n", exceptions);
- if (exceptions == (u32)-1) {
+ if (exceptions == VFP_EXCEPTION_ERROR) {
vfp_panic("unhandled bounce");
vfp_raise_sigfpe(0, regs);
return;
@@ -170,7 +170,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
*/
static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
{
- u32 exceptions = (u32)-1;
+ u32 exceptions = VFP_EXCEPTION_ERROR;
pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index dae2c2f46052..78d7cac5f36b 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -506,7 +506,7 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
vdd.exponent = 2047;
- if (tm & VFP_NAN)
+ if (tm == VFP_QNAN)
vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
goto pack_nan;
} else if (tm & VFP_ZERO)
@@ -514,10 +514,6 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
else
vdd.exponent = vsm.exponent + (1023 - 127);
- /*
- * Technically, if bit 0 of dd is set, this is an invalid
- * instruction. However, we ignore this for efficiency.
- */
return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
pack_nan:
@@ -1174,7 +1170,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int sd = vfp_get_sd(inst);
+ unsigned int dest;
unsigned int sn = vfp_get_sn(inst);
unsigned int sm = vfp_get_sm(inst);
unsigned int vecitr, veclen, vecstride;
@@ -1184,10 +1180,22 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
/*
+ * fcvtsd takes a dN register number as destination, not sN.
+ * Technically, if bit 0 of dd is set, this is an invalid
+ * instruction. However, we ignore this for efficiency.
+ * It also only operates on scalars.
+ */
+ if ((inst & FEXT_MASK) == FEXT_FCVT) {
+ veclen = 0;
+ dest = vfp_get_dd(inst);
+ } else
+ dest = vfp_get_sd(inst);
+
+ /*
* If destination bank is zero, vector length is always '1'.
* ARM DDI0100F C5.1.3, C5.3.2.
*/
- if (FREG_BANK(sd) == 0)
+ if (FREG_BANK(dest) == 0)
veclen = 0;
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1201,15 +1209,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
s32 m = vfp_get_float(sm);
u32 except;
- if (op == FOP_EXT)
+ if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+ pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
+ else if (op == FOP_EXT)
pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m);
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
else
pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, sd, sn,
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn,
FOP_TO_IDX(op), sm, m);
- except = fop(sd, sn, m, fpscr);
+ except = fop(dest, sn, m, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
vecitr >> FPSCR_LENGTH_BIT, except);
@@ -1227,7 +1238,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
* we encounter an exception. We continue.
*/
- sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7);
+ dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
if (FREG_BANK(sm) != 0)
sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);