aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorPaul Sokolovsky <pmiscml@gmail.com>2006-08-27 12:54:56 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-08-27 12:54:56 +0100
commit8f1bf8743c459399685f5df43021acd156548c22 (patch)
tree3eab5454e3dd04765f0f8b8d9f490596260d0ec5 /arch/arm
parentb53a2b41f156a9c9b62c14502037cbc15bc08b54 (diff)
[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>
Diffstat (limited to 'arch/arm')
-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-sa1100/ssp.c46
3 files changed, 78 insertions, 23 deletions
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index f9421318cb7..ff6b4ee037f 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 93096befd01..1fddfeaa630 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 1604dadf27f..5eba5fbbb56 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;
}
/**