diff options
Diffstat (limited to 'arch/arm/mach-pxa/ssp.c')
| -rw-r--r-- | arch/arm/mach-pxa/ssp.c | 35 |
1 files changed, 28 insertions, 7 deletions
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 @@ | |||
| 40 | 40 | ||
| 41 | #define PXA_SSP_PORTS 3 | 41 | #define PXA_SSP_PORTS 3 |
| 42 | 42 | ||
| 43 | #define TIMEOUT 100000 | ||
| 44 | |||
| 43 | struct ssp_info_ { | 45 | struct ssp_info_ { |
| 44 | int irq; | 46 | int irq; |
| 45 | u32 clock; | 47 | u32 clock; |
| @@ -92,13 +94,18 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
| 92 | * The caller is expected to perform the necessary locking. | 94 | * The caller is expected to perform the necessary locking. |
| 93 | * | 95 | * |
| 94 | * Returns: | 96 | * Returns: |
| 95 | * %-ETIMEDOUT timeout occurred (for future) | 97 | * %-ETIMEDOUT timeout occurred |
| 96 | * 0 success | 98 | * 0 success |
| 97 | */ | 99 | */ |
| 98 | int ssp_write_word(struct ssp_dev *dev, u32 data) | 100 | int ssp_write_word(struct ssp_dev *dev, u32 data) |
| 99 | { | 101 | { |
| 100 | while (!(SSSR_P(dev->port) & SSSR_TNF)) | 102 | int timeout = TIMEOUT; |
| 103 | |||
| 104 | while (!(SSSR_P(dev->port) & SSSR_TNF)) { | ||
| 105 | if (!--timeout) | ||
| 106 | return -ETIMEDOUT; | ||
| 101 | cpu_relax(); | 107 | cpu_relax(); |
| 108 | } | ||
| 102 | 109 | ||
| 103 | SSDR_P(dev->port) = data; | 110 | SSDR_P(dev->port) = data; |
| 104 | 111 | ||
| @@ -117,15 +124,21 @@ int ssp_write_word(struct ssp_dev *dev, u32 data) | |||
| 117 | * The caller is expected to perform the necessary locking. | 124 | * The caller is expected to perform the necessary locking. |
| 118 | * | 125 | * |
| 119 | * Returns: | 126 | * Returns: |
| 120 | * %-ETIMEDOUT timeout occurred (for future) | 127 | * %-ETIMEDOUT timeout occurred |
| 121 | * 32-bit data success | 128 | * 32-bit data success |
| 122 | */ | 129 | */ |
| 123 | int ssp_read_word(struct ssp_dev *dev) | 130 | int ssp_read_word(struct ssp_dev *dev, u32 *data) |
| 124 | { | 131 | { |
| 125 | while (!(SSSR_P(dev->port) & SSSR_RNE)) | 132 | int timeout = TIMEOUT; |
| 133 | |||
| 134 | while (!(SSSR_P(dev->port) & SSSR_RNE)) { | ||
| 135 | if (!--timeout) | ||
| 136 | return -ETIMEDOUT; | ||
| 126 | cpu_relax(); | 137 | cpu_relax(); |
| 138 | } | ||
| 127 | 139 | ||
| 128 | return SSDR_P(dev->port); | 140 | *data = SSDR_P(dev->port); |
| 141 | return 0; | ||
| 129 | } | 142 | } |
| 130 | 143 | ||
| 131 | /** | 144 | /** |
| @@ -136,13 +149,21 @@ int ssp_read_word(struct ssp_dev *dev) | |||
| 136 | * | 149 | * |
| 137 | * The caller is expected to perform the necessary locking. | 150 | * The caller is expected to perform the necessary locking. |
| 138 | */ | 151 | */ |
| 139 | void ssp_flush(struct ssp_dev *dev) | 152 | int ssp_flush(struct ssp_dev *dev) |
| 140 | { | 153 | { |
| 154 | int timeout = TIMEOUT * 2; | ||
| 155 | |||
| 141 | do { | 156 | do { |
| 142 | while (SSSR_P(dev->port) & SSSR_RNE) { | 157 | while (SSSR_P(dev->port) & SSSR_RNE) { |
| 158 | if (!--timeout) | ||
| 159 | return -ETIMEDOUT; | ||
| 143 | (void) SSDR_P(dev->port); | 160 | (void) SSDR_P(dev->port); |
| 144 | } | 161 | } |
| 162 | if (!--timeout) | ||
| 163 | return -ETIMEDOUT; | ||
| 145 | } while (SSSR_P(dev->port) & SSSR_BSY); | 164 | } while (SSSR_P(dev->port) & SSSR_BSY); |
| 165 | |||
| 166 | return 0; | ||
| 146 | } | 167 | } |
| 147 | 168 | ||
| 148 | /** | 169 | /** |
