X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Farm%2Fmach-pxa%2Fssp.c;h=71766ac0328b1378f23afde4a656143fd4ba4d2e;hb=fe47463d4117e8f20905246ee660aa15eb811a18;hp=a68b30eff4d26180c24e4ed44545980f04188d64;hpb=4060994c3e337b40e0f6fa8ce2cc178e021baf3d;p=linux-2.6-omap-h63xx.git diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index a68b30eff4d..71766ac0328 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,8 @@ #define PXA_SSP_PORTS 3 +#define TIMEOUT 100000 + struct ssp_info_ { int irq; u32 clock; @@ -49,20 +52,20 @@ struct ssp_info_ { */ static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = { #if defined (CONFIG_PXA27x) - {IRQ_SSP, CKEN23_SSP1}, - {IRQ_SSP2, CKEN3_SSP2}, - {IRQ_SSP3, CKEN4_SSP3}, + {IRQ_SSP, CKEN_SSP1}, + {IRQ_SSP2, CKEN_SSP2}, + {IRQ_SSP3, CKEN_SSP3}, #else - {IRQ_SSP, CKEN3_SSP}, - {IRQ_NSSP, CKEN9_NSSP}, - {IRQ_ASSP, CKEN10_ASSP}, + {IRQ_SSP, CKEN_SSP}, + {IRQ_NSSP, CKEN_NSSP}, + {IRQ_ASSP, CKEN_ASSP}, #endif }; -static DECLARE_MUTEX(sem); +static DEFINE_MUTEX(mutex); static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; -static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ssp_interrupt(int irq, void *dev_id) { struct ssp_dev *dev = (struct ssp_dev*) dev_id; unsigned int status = SSSR_P(dev->port); @@ -91,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; @@ -116,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; } /** @@ -135,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; } /** @@ -239,16 +261,16 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags) if (port > PXA_SSP_PORTS || port == 0) return -ENODEV; - down(&sem); + mutex_lock(&mutex); if (use_count[port - 1]) { - up(&sem); + mutex_unlock(&mutex); return -EBUSY; } use_count[port - 1]++; if (!request_mem_region(__PREG(SSCR0_P(port)), 0x2c, "SSP")) { use_count[port - 1]--; - up(&sem); + mutex_unlock(&mutex); return -EBUSY; } dev->port = port; @@ -265,13 +287,13 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags) /* turn on SSP port clock */ pxa_set_cken(ssp_info[port-1].clock, 1); - up(&sem); + mutex_unlock(&mutex); return 0; out_region: release_mem_region(__PREG(SSCR0_P(port)), 0x2c); use_count[port - 1]--; - up(&sem); + mutex_unlock(&mutex); return ret; } @@ -282,7 +304,7 @@ out_region: */ void ssp_exit(struct ssp_dev *dev) { - down(&sem); + mutex_lock(&mutex); SSCR0_P(dev->port) &= ~SSCR0_SSE; if (dev->port > PXA_SSP_PORTS || dev->port == 0) { @@ -295,7 +317,7 @@ void ssp_exit(struct ssp_dev *dev) free_irq(dev->irq, dev); release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); use_count[dev->port - 1]--; - up(&sem); + mutex_unlock(&mutex); } EXPORT_SYMBOL(ssp_write_word);