Skip to content

Commit

Permalink
[ARM] 3760/1: This patch adds timeouts while working with SSP registe…
Browse files Browse the repository at this point in the history
…rs. 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>
  • Loading branch information
Paul Sokolovsky authored and Russell King committed Aug 27, 2006
1 parent b53a2b4 commit 8f1bf87
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 27 deletions.
20 changes: 12 additions & 8 deletions arch/arm/mach-pxa/corgi_ssp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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)
Expand All @@ -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));
Expand Down
35 changes: 28 additions & 7 deletions arch/arm/mach-pxa/ssp.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@

#define PXA_SSP_PORTS 3

#define TIMEOUT 100000

struct ssp_info_ {
int irq;
u32 clock;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}

/**
Expand All @@ -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;
}

/**
Expand Down
46 changes: 38 additions & 8 deletions arch/arm/mach-sa1100/ssp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}

/**
Expand All @@ -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;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions include/asm-arm/arch-pxa/ssp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions include/asm-arm/hardware/ssp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 8f1bf87

Please sign in to comment.