From 7c6f25141b88b5e926f9d43932ce668602d611ae Mon Sep 17 00:00:00 2001
From: Daniel Jacobowitz <drow@false.org>
Date: Sun, 27 Aug 2006 12:42:08 +0100
Subject: [ARM] 3748/3: Correct error check in vfp_raise_exceptions

Patch from Daniel Jacobowitz

The recent fix to hide VFP_NAN_FLAG broke the check in vfp_raise_exceptions;
it would attempt to deliver an exception mask of 0xfffffeff instead of reporting
a serious error condition using printk.  Define a safe constant to use for
an invalid exception maskm, and use it at both ends.

Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/vfp/vfp.h       | 8 ++++++++
 arch/arm/vfp/vfpmodule.c | 4 ++--
 2 files changed, 10 insertions(+), 2 deletions(-)

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/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);
 
-- 
cgit v1.2.3


From c29ecac18cb740ae845db14963ac586c53962453 Mon Sep 17 00:00:00 2001
From: Daniel Jacobowitz <drow@false.org>
Date: Sun, 27 Aug 2006 12:42:10 +0100
Subject: [ARM] 3749/3: Correct VFP single/double conversion emulation

Patch from Daniel Jacobowitz

The fcvtsd/fcvtds emulation was left behind when the numbering of double
precision registers was changed from 0-30 to 0-15.  Both conversion
instructions were writing their results to the wrong register.  Also,
the conversion instructions should stop after the first element even
if a vector length is specified.

Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/vfp/vfpdouble.c | 28 +++++++++++++++++++++-------
 arch/arm/vfp/vfpsingle.c | 33 ++++++++++++++++++++++-----------
 2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 009038c8113e..021581680e94 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -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;
@@ -1136,11 +1136,21 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
 	veclen = fpscr & FPSCR_LENGTH_MASK;
 	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/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index dae2c2f46052..5bbd5d1c8a5f 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -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;
@@ -1183,11 +1179,23 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
 	veclen = fpscr & FPSCR_LENGTH_MASK;
 	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);
-- 
cgit v1.2.3


From b53a2b41f156a9c9b62c14502037cbc15bc08b54 Mon Sep 17 00:00:00 2001
From: Daniel Jacobowitz <drow@false.org>
Date: Sun, 27 Aug 2006 12:42:14 +0100
Subject: [ARM] 3758/1: Preserve signalling NaNs in conversion

Patch from Daniel Jacobowitz

The fcvtds and fcvtsd instructions were generating a qnan bit pattern
for both quiet and signalling NaNs.

Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/vfp/vfpdouble.c | 2 +-
 arch/arm/vfp/vfpsingle.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 021581680e94..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)
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 5bbd5d1c8a5f..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)
-- 
cgit v1.2.3


From 8f1bf8743c459399685f5df43021acd156548c22 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky <pmiscml@gmail.com>
Date: Sun, 27 Aug 2006 12:54:56 +0100
Subject: [ARM] 3760/1: This patch adds timeouts while working with SSP
 registers. Such timeouts were en

Patch from Paul Sokolovsky

This patch adds timeouts while working with SSP registers. Such
timeouts were envisioned by docstrings in ssp.c, but were not
implemented. There were actual lockups while accessing
touchscreen for iPaqs h1910, h4000 due to lack of the timeouts.
This is updated version of previously submitted patch: 3738/1.

Signed-off-by: Paul Sokolovsky <pmiscml@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-pxa/corgi_ssp.c  | 20 ++++++++++--------
 arch/arm/mach-pxa/ssp.c        | 35 +++++++++++++++++++++++++-------
 arch/arm/mach-sa1100/ssp.c     | 46 ++++++++++++++++++++++++++++++++++--------
 include/asm-arm/arch-pxa/ssp.h |  4 ++--
 include/asm-arm/hardware/ssp.h |  4 ++--
 5 files changed, 82 insertions(+), 27 deletions(-)

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-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/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h
index 949878c0d908..ea200551a75f 100644
--- a/include/asm-arm/arch-pxa/ssp.h
+++ b/include/asm-arm/arch-pxa/ssp.h
@@ -40,8 +40,8 @@ struct ssp_dev {
 };
 
 int ssp_write_word(struct ssp_dev *dev, u32 data);
-int ssp_read_word(struct ssp_dev *dev);
-void ssp_flush(struct ssp_dev *dev);
+int ssp_read_word(struct ssp_dev *dev, u32 *data);
+int ssp_flush(struct ssp_dev *dev);
 void ssp_enable(struct ssp_dev *dev);
 void ssp_disable(struct ssp_dev *dev);
 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
diff --git a/include/asm-arm/hardware/ssp.h b/include/asm-arm/hardware/ssp.h
index 28aa11b769cd..3b42e181997c 100644
--- a/include/asm-arm/hardware/ssp.h
+++ b/include/asm-arm/hardware/ssp.h
@@ -16,8 +16,8 @@ struct ssp_state {
 };
 
 int ssp_write_word(u16 data);
-int ssp_read_word(void);
-void ssp_flush(void);
+int ssp_read_word(u16 *data);
+int ssp_flush(void);
 void ssp_enable(void);
 void ssp_disable(void);
 void ssp_save_state(struct ssp_state *ssp);
-- 
cgit v1.2.3


From 416112f818afcc08aeaba79ebba899aee5ddf571 Mon Sep 17 00:00:00 2001
From: David Brownell <david-b@pacbell.net>
Date: Sun, 27 Aug 2006 13:09:14 +0100
Subject: [ARM] 3741/1: remove sa1111.c build warning on non-sa1100 systems

Patch from David Brownell

Remove buld warning when building sa1111 on non-sa1100 platforms (e.g. PXA).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/common/sa1111.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

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
 
 	/*
-- 
cgit v1.2.3


From 7034b0e60a2ccfab4ee2d3a468cb8cad6de3740d Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Mon, 28 Aug 2006 12:44:03 +0100
Subject: [ARM] Arrange for isa.c to use named initialisers

Convert isa.c (the glibc interface for emulating ISA IO) to use
named initialisers.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/isa.c | 63 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 21 deletions(-)

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)
-- 
cgit v1.2.3


From 1645f20bc4440d6f67f73f570f3cf873b4e37f3c Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Mon, 28 Aug 2006 12:45:16 +0100
Subject: [ARM] Move prototype for register_isa_ports to asm/io.h

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-footbridge/dc21285.c | 1 -
 include/asm-arm/io.h               | 7 +++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

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/include/asm-arm/io.h b/include/asm-arm/io.h
index b3479fc1cc8f..bf7b9dea30f1 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -291,5 +291,12 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
  */
 #define xlate_dev_kmem_ptr(p)	p
 
+/*
+ * Register ISA memory and port locations for glibc iopl/inb/outb
+ * emulation.
+ */
+extern void register_isa_ports(unsigned int mmio, unsigned int io,
+			       unsigned int io_shift);
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_ARM_IO_H */
-- 
cgit v1.2.3


From 863dab453b869136453944bda63e20b6ed39c5ef Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Mon, 28 Aug 2006 12:47:05 +0100
Subject: [ARM] Add Integrator support for glibc outb() and friends

Add the necessary call to register_isa_ports() so that glibc knows
where these are found on Integrator platforms.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/Makefile          | 3 +--
 arch/arm/mach-integrator/pci_v3.c | 2 ++
 2 files changed, 3 insertions(+), 2 deletions(-)

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/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);
 }
-- 
cgit v1.2.3


From 260e98edc8ae8ea862c9c222eeffb1a2eeafa7fc Mon Sep 17 00:00:00 2001
From: Lennert Buytenhek <buytenh@wantstofly.org>
Date: Mon, 28 Aug 2006 12:51:20 +0100
Subject: [ARM] 3761/1: fix armv4t breakage after adding thumb interworking to
 userspace helpers

Patch from Lennert Buytenhek

On armv4t systems, we have always compiled the kernel with -march=armv4
instead of -march=armv4t, which means that any use of bx will bomb out.

Commit ba9b5d76372dc290b6ca04dad93927a22c2ac49a introduced the use of
bx in the kernel, which means we need to compile with -march=armv4t on
armv4t systems now.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/Makefile   |  3 ++-
 arch/arm/mm/Kconfig | 13 +++++++++----
 2 files changed, 11 insertions(+), 5 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/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
-- 
cgit v1.2.3